[
  {
    "path": ".github/dependabot.yml",
    "content": "{\n  \"updates\": [\n    {\n      \"directory\": \"/\",\n      \"package-ecosystem\": \"github-actions\",\n      \"schedule\": {\n        \"interval\": \"weekly\"\n      }\n    }\n  ],\n  \"version\": 2\n}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "jobs:\n  build:\n    name: GHC ${{ matrix.ghc }} on ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v6\n      - run: mkdir artifact\n      - uses: haskell/ghcup-setup@v1\n        with:\n          ghc: ${{ matrix.ghc }}\n          cabal: latest\n      - run: ghc-pkg list\n      - run: cabal sdist --output-dir artifact\n      - run: cabal configure --enable-documentation --enable-tests --flags=pedantic --haddock-for-hackage --jobs\n      - run: cat cabal.project.local\n      - run: cp cabal.project.local artifact\n      - run: cabal update\n      - run: cabal freeze\n      - run: cat cabal.project.freeze\n      - run: cp cabal.project.freeze artifact\n      - run: cabal outdated --v2-freeze-file\n      - uses: actions/cache@v5\n        with:\n          key: ${{ matrix.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}\n          path: ~/.local/state/cabal\n          restore-keys: ${{ matrix.os }}-${{ matrix.ghc }}-\n      - run: cabal build --only-download\n      - run: cabal build --only-dependencies\n      - run: cabal build\n      - run: cp dist-newstyle/flow-*-docs.tar.gz artifact\n      - run: tar --create --file artifact.tar --verbose artifact\n      - uses: actions/upload-artifact@v7\n        with:\n          name: flow-${{ github.sha }}-${{ matrix.os }}-${{ matrix.ghc }}\n          path: artifact.tar\n      - run: cabal run -- flow-test-suite --randomize --strict\n    strategy:\n      matrix:\n        include:\n          - ghc: 9.12\n            os: macos-14\n          - ghc: '9.10'\n            os: ubuntu-24.04\n          - ghc: 9.12\n            os: ubuntu-24.04\n          - ghc: 9.14\n            os: ubuntu-24.04\n          - ghc: 9.12\n            os: windows-2022\n  cabal:\n    name: Cabal\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - run: cabal check\n  gild:\n    name: Gild\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: tfausak/cabal-gild-setup-action@v2\n      - run: cabal-gild --input flow.cabal --mode check\n  hlint:\n    name: HLint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: haskell-actions/hlint-setup@v2\n      - uses: haskell-actions/hlint-run@v2\n        with:\n          fail-on: status\n  ormolu:\n    name: Ormolu\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: haskell-actions/run-ormolu@v17\n  release:\n    if: ${{ github.event_name == 'release' }}\n    name: Release\n    needs: build\n    permissions:\n      contents: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/download-artifact@v8\n        with:\n          name: flow-${{ github.sha }}-ubuntu-24.04-9.12\n      - run: tar --extract --file artifact.tar --verbose\n      - uses: softprops/action-gh-release@v3\n        with:\n          files: artifact/flow-${{ github.event.release.tag_name }}.tar.gz\n      - run: cabal upload --publish --username '${{ secrets.HACKAGE_USERNAME }}' --password '${{ secrets.HACKAGE_PASSWORD }}' artifact/flow-${{ github.event.release.tag_name }}.tar.gz\n      - run: cabal --http-transport=plain-http upload --documentation --publish --username '${{ secrets.HACKAGE_USERNAME }}' --password '${{ secrets.HACKAGE_PASSWORD }}' artifact/flow-${{ github.event.release.tag_name }}-docs.tar.gz\nname: CI\non:\n  pull_request:\n    branches:\n      - main\n  push:\n    branches:\n      - main\n  release:\n    types:\n      - created\n"
  },
  {
    "path": ".gitignore",
    "content": "/.vscode/\n/cabal.project.*\n/dist-newstyle/\n"
  },
  {
    "path": ".hlint.yaml",
    "content": "[\n  {\n    \"group\": {\n      \"enabled\": true,\n      \"name\": \"dollar\"\n    }\n  },\n  {\n    \"group\": {\n      \"enabled\": true,\n      \"name\": \"generalise\"\n    }\n  },\n  {\n    \"ignore\": {\n      \"name\": \"Avoid lambda\"\n    }\n  },\n  {\n    \"ignore\": {\n      \"name\": \"Redundant lambda\"\n    }\n  },\n  {\n    \"ignore\": {\n      \"name\": \"Use lambda-case\"\n    }\n  },\n  {\n    \"ignore\": {\n      \"name\": \"Use tuple-section\"\n    }\n  }\n]\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change log\n\nFlow follows the [Package Versioning Policy](https://pvp.haskell.org).\nYou can find release notes [on GitHub](https://github.com/tfausak/flow/releases).\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2026 Taylor Fausak\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# [Flow][]\n\n[![CI](https://github.com/tfausak/flow/actions/workflows/ci.yml/badge.svg)](https://github.com/tfausak/flow/actions/workflows/ci.yml)\n[![Hackage](https://badgen.net/hackage/v/flow)](https://hackage.haskell.org/package/flow)\n\nWrite more understandable Haskell.\n\nFlow is a package that provides functions and operators for writing more\nunderstandable Haskell. It is an alternative to some common idioms like\n[`($)`][] for function application and [`(.)`][] for function composition.\n\n-   [Requirements](#requirements)\n-   [Installation](#installation)\n-   [Usage](#usage)\n    -   [Cheat sheet](#cheat-sheet)\n\n## Requirements\n\nFlow requires a Haskell compiler. It is tested with recent versions of GHC, but\nolder or different compilers should be acceptable. For installation with Cabal,\nFlow requires at least Cabal 2.2.\n\n## Installation\n\nTo add Flow as a dependency to your package, add it to your Cabal file.\n\n```\nbuild-depends: flow ==2.0.*\n```\n\n## Usage\n\nFlow is designed to be imported unqualified. It does not export anything that\nconflicts with [the base package][].\n\n``` hs\nimport Flow\n```\n\n### Cheat sheet\n\nFlow            | Base\n--------------- | -------------\n<code>x &#124;> f</code> | `x & f`\n<code>f <&#124; x</code> | `f $ x`\n`apply x f`     | `f x`\n`f .> g`        | `f >>> g`\n`g <. f`        | `g . f`\n`compose f g x` | `g (f x)`\n`x !> f`        | -\n`f <! x`        | `f $! x`\n`apply' x f`    | `seq x (f x)`\n\n### Converting existing code\n\nIf you want to uniformly use flow operators you can use [HLint] with the\n`hlint-flow.yaml` file. For easy use, it is best to extract the\n`hlint-flow.yaml` to your project directory and do\n\n``` sh\n> hlint -h hlint-flow.yaml <source file>\n```\n\nor\n\n``` sh\n> hlint --git -h hlint-flow.yaml\n```\n\nto check all Haskell source tracked by git.\n\nFor more information about Flow, please read [the Haddock documentation][].\n\n[HLint]: https://github.com/ndmitchell/hlint\n[Flow]: http://taylor.fausak.me/flow/\n[`($)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:-36-\n[`(.)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:.\n[the base package]: http://hackage.haskell.org/package/base\n[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html\n"
  },
  {
    "path": "cabal.project",
    "content": "packages: .\n"
  },
  {
    "path": "flow.cabal",
    "content": "cabal-version: 2.2\nname: flow\nversion: 2.0.0.11\nsynopsis: Write more understandable Haskell.\ndescription: Flow provides operators for writing more understandable Haskell.\nbuild-type: Simple\ncategory: Combinators, Functions, Utility\nextra-doc-files:\n  CHANGELOG.md\n  README.md\n\nlicense-file: LICENSE.txt\nlicense: MIT\nmaintainer: Taylor Fausak\n\nsource-repository head\n  location: https://github.com/tfausak/flow\n  type: git\n\nflag pedantic\n  default: False\n  description: Enables @-Werror@, which turns warnings into errors.\n  manual: True\n\ncommon library\n  build-depends: base ^>=4.20.0.0 || ^>=4.21.0.0 || ^>=4.22.0.0\n  default-language: Haskell2010\n  ghc-options:\n    -Weverything\n    -Wno-all-missed-specialisations\n    -Wno-implicit-prelude\n    -Wno-missing-exported-signatures\n    -Wno-missing-safe-haskell-mode\n    -Wno-prepositive-qualified-module\n    -Wno-safe\n\n  if flag(pedantic)\n    ghc-options: -Werror\n\ncommon executable\n  import: library\n  build-depends: flow\n  ghc-options:\n    -rtsopts\n    -threaded\n\nlibrary\n  import: library\n  -- cabal-gild: discover source/library\n  exposed-modules: Flow\n  hs-source-dirs: source/library\n\ntest-suite flow-test-suite\n  import: executable\n  build-depends:\n    HUnit ^>=1.6.2.0\n\n  hs-source-dirs: source/test-suite\n  main-is: Main.hs\n  type: exitcode-stdio-1.0\n"
  },
  {
    "path": "hlint-flow.yaml",
    "content": "- hint: \n    lhs: 'f $! x'\n    note: 'Use `<!`'\n    rhs: 'f <! x'\n\n- hint: \n    lhs: 'f $ x'\n    note: 'Use `<|`'\n    rhs: 'f <| x'\n\n- hint: \n    lhs: 'x & f'\n    note: 'Use `|>`'\n    rhs: 'f |> x'\n\n- hint: \n    lhs: 'f . g'\n    note: 'Use `<.`'\n    rhs: 'f <. g'\n\n- hint: \n    lhs: 'f <. g'\n    note: 'Use `.>` for natural reading direction'\n    rhs: 'g .> f'\n\n"
  },
  {
    "path": "source/library/Flow.hs",
    "content": "-- | Flow provides operators for writing more understandable Haskell. It is an\n-- alternative to some common idioms like ('Prelude.$') for function\n-- application and ('Prelude..') for function composition.\n--\n-- Flow is designed to be imported unqualified. It does not export anything\n-- that conflicts with the base package.\n--\n-- >>> import Flow\n--\n-- == Rationale\n--\n-- I think that Haskell can be hard to read. It has two operators for applying\n-- functions. Both are not really necessary and only serve to reduce\n-- parentheses. But they make code hard to read. People who do not already\n-- know Haskell have no chance of guessing what @foo $ bar@ or @baz & qux@\n-- mean.\n--\n-- Those that do know Haskell are forced to read lines forwards and backwards\n-- at the same time, thanks to function composition. Even something simple,\n-- like finding the minimum element, bounces around: @f = head . sort@.\n--\n-- I think we can do better. By using directional operators, we can allow\n-- readers to move their eye in only one direction, be that left-to-right or\n-- right-to-left. And by using idioms common in other programming languages,\n-- we can allow people who aren't familiar with Haskell to guess at the\n-- meaning.\n--\n-- So instead of ('Prelude.$'), I propose ('<|'). It is a pipe, which anyone\n-- who has touched a Unix system should be familiar with. And it points in the\n-- direction it sends arguments along. Similarly, replace ('Data.Function.&')\n-- with ('|>'). And for composition, ('<.') replaces ('Prelude..'). I would\n-- have preferred @<<@, but its counterpart @>>@ is taken by Haskell's syntax.\n-- So-called \"backwards\" composition is normally expressed with\n-- ('Control.Category.>>>'), which Flow provides as ('.>').\nmodule Flow\n  ( -- * Function application\n    (|>),\n    (<|),\n    apply,\n\n    -- * Function composition\n    (.>),\n    (<.),\n    compose,\n\n    -- * Strict function application\n    (!>),\n    (<!),\n    apply',\n  )\nwhere\n\nimport qualified Prelude\n\n-- | Left-associative 'apply' operator. Read as \"apply forward\" or \"pipe into\".\n-- Use this to create long chains of computation that suggest which direction\n-- things move in.\n--\n-- >>> 3 |> succ |> recip |> negate\n-- -0.25\n--\n-- Or use it anywhere you would use ('Data.Function.&').\n--\n-- prop> \\ x -> (x |> f) == f x\n--\n-- prop> \\ x -> (x |> f |> g) == g (f x)\ninfixl 0 |>\n\n{-# INLINE (|>) #-}\n(|>) :: a -> (a -> b) -> b\n(|>) = apply\n\n-- | Right-associative 'apply' operator. Read as \"apply backward\" or \"pipe\n-- from\". Use this to create long chains of computation that suggest which\n-- direction things move in. You may prefer this operator over ('|>') for\n-- 'Prelude.IO' actions since it puts the last function first.\n--\n-- >>> print <| negate <| recip <| succ <| 3\n-- -0.25\n--\n-- Or use it anywhere you would use ('Prelude.$').\n--\n-- Note that ('<|') and ('|>') have the same precedence, so they cannot be used\n-- together.\n--\n-- >>> -- This doesn't work!\n-- >>> -- print <| 3 |> succ |> recip |> negate\n--\n-- prop> \\ x -> (f <| x) == f x\n--\n-- prop> \\ x -> (g <| f <| x) == g (f x)\ninfixr 0 <|\n\n{-# INLINE (<|) #-}\n(<|) :: (a -> b) -> a -> b\n(<|) f = f\n\n-- | Function application. This function usually isn't necessary, but it can be\n-- more readable than some alternatives when used with higher-order functions\n-- like 'Prelude.map'.\n--\n-- >>> map (apply 2) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n--\n-- In general you should prefer using an explicit lambda or operator section.\n--\n-- >>> map (\\ f -> 2 |> f) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n-- >>> map (2 |>) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n-- >>> map (<| 2) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n--\n-- prop> \\ x -> apply x f == f x\n{-# INLINE apply #-}\napply :: a -> (a -> b) -> b\napply x f = f x\n\n-- | Left-associative 'compose' operator. Read as \"compose forward\" or \"and\n-- then\". Use this to create long chains of computation that suggest which\n-- direction things move in.\n--\n-- >>> let f = succ .> recip .> negate\n-- >>> f 3\n-- -0.25\n--\n-- Or use it anywhere you would use ('Control.Category.>>>').\n--\n-- prop> \\ x -> (f .> g) x == g (f x)\n--\n-- prop> \\ x -> (f .> g .> h) x == h (g (f x))\ninfixl 9 .>\n\n{-# INLINE (.>) #-}\n(.>) :: (a -> b) -> (b -> c) -> (a -> c)\nf .> g = compose f g\n\n-- | Right-associative 'compose' operator. Read as \"compose backward\" or \"but\n-- first\". Use this to create long chains of computation that suggest which\n-- direction things move in. You may prefer this operator over ('.>') for\n-- 'Prelude.IO' actions since it puts the last function first.\n--\n-- >>> let f = print <. negate <. recip <. succ\n-- >>> f 3\n-- -0.25\n--\n-- Or use it anywhere you would use ('Prelude..').\n--\n-- Note that ('<.') and ('.>') have the same precedence, so they cannot be used\n-- together.\n--\n-- >>> -- This doesn't work!\n-- >>> -- print <. succ .> recip .> negate\n--\n-- prop> \\ x -> (g <. f) x == g (f x)\n--\n-- prop> \\ x -> (h <. g <. f) x == h (g (f x))\ninfixr 9 <.\n\n{-# INLINE (<.) #-}\n(<.) :: (b -> c) -> (a -> b) -> (a -> c)\ng <. f = compose f g\n\n-- | Function composition. This function usually isn't necessary, but it can be\n-- more readable than some alternatives when used with higher-order functions\n-- like 'Prelude.map'.\n--\n-- >>> let fs = map (compose succ) [recip, negate]\n-- >>> map (apply 3) fs\n-- [0.25,-4.0]\n--\n-- In general you should prefer using an explicit lambda or operator section.\n--\n-- >>> map (\\ f -> f 3) (map (\\ f -> succ .> f) [recip, negate])\n-- [0.25,-4.0]\n-- >>> map (\\ f -> f 3) (map (succ .>) [recip, negate])\n-- [0.25,-4.0]\n-- >>> map (\\ f -> f 3) (map (<. succ) [recip, negate])\n-- [0.25,-4.0]\n--\n-- prop> \\ x -> compose f g x == g (f x)\n{-# INLINE compose #-}\ncompose :: (a -> b) -> (b -> c) -> (a -> c)\ncompose f g = \\x -> g (f x)\n\n-- | Left-associative 'apply'' operator. Read as \"strict apply forward\" or\n-- \"strict pipe into\". Use this to create long chains of computation that\n-- suggest which direction things move in.\n--\n-- >>> 3 !> succ !> recip !> negate\n-- -0.25\n--\n-- The difference between this and ('|>') is that this evaluates its argument\n-- before passing it to the function.\n--\n-- >>> undefined |> const True\n-- True\n-- >>> undefined !> const True\n-- *** Exception: Prelude.undefined\n-- ...\n--\n-- prop> \\ x -> (x !> f) == seq x (f x)\n--\n-- prop> \\ x -> (x !> f !> g) == let y = seq x (f x) in seq y (g y)\ninfixl 0 !>\n\n{-# INLINE (!>) #-}\n(!>) :: a -> (a -> b) -> b\n(!>) = \\x f -> f <! x\n\n-- | Right-associative 'apply'' operator. Read as \"strict apply backward\" or\n-- \"strict pipe from\". Use this to create long chains of computation that\n-- suggest which direction things move in. You may prefer this operator over\n-- ('!>') for 'Prelude.IO' actions since it puts the last function first.\n--\n-- >>> print <! negate <! recip <! succ <! 3\n-- -0.25\n--\n-- Or use it anywhere you would use ('Prelude.$!').\n--\n-- The difference between this and ('<|') is that this evaluates its argument\n-- before passing it to the function.\n--\n-- >>> const True <| undefined\n-- True\n-- >>> const True <! undefined\n-- *** Exception: Prelude.undefined\n-- ...\n--\n-- Note that ('<!') and ('!>') have the same precedence, so they cannot be used\n-- together.\n--\n-- >>> -- This doesn't work!\n-- >>> -- print <! 3 !> succ !> recip !> negate\n--\n-- prop> \\ x -> (f <! x) == seq x (f x)\n--\n-- prop> \\ x -> (g <! f <! x) == let y = seq x (f x) in seq y (g y)\ninfixr 0 <!\n\n{-# INLINE (<!) #-}\n(<!) :: (a -> b) -> a -> b\n(<!) = (Prelude.$!)\n\n-- | Strict function application. This function usually isn't necessary, but it\n-- can be more readable than some alternatives when used with higher-order\n-- functions like 'Prelude.map'.\n--\n-- >>> map (apply' 2) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n--\n-- The different between this and 'apply' is that this evaluates its argument\n-- before passing it to the function.\n--\n-- >>> apply undefined (const True)\n-- True\n-- >>> apply' undefined (const True)\n-- *** Exception: Prelude.undefined\n-- ...\n--\n-- In general you should prefer using an explicit lambda or operator section.\n--\n-- >>> map (\\ f -> 2 !> f) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n-- >>> map (2 !>) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n-- >>> map (<! 2) [succ, recip, negate]\n-- [3.0,0.5,-2.0]\n--\n-- prop> \\ x -> apply' x f == seq x (f x)\n{-# INLINE apply' #-}\napply' :: a -> (a -> b) -> b\napply' = (!>)\n"
  },
  {
    "path": "source/test-suite/Main.hs",
    "content": "import qualified Control.Monad as Monad\nimport qualified Flow\nimport qualified System.Exit as Exit\nimport qualified Test.HUnit as Test\n\nmain :: IO ()\nmain = do\n  counts <-\n    Test.runTestTT $\n      Test.TestList\n        [ True Test.~?= True,\n          (3 Flow.|> succ Flow.|> recip Flow.|> negate) Test.~?= (-0.25 :: Double),\n          (negate Flow.<| recip Flow.<| succ Flow.<| 3) Test.~?= (-0.25 :: Double),\n          fmap (Flow.apply 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (Flow.<| 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (Flow.apply 3 . Flow.compose succ) [recip, negate]\n            Test.~?= [0.25, -4 :: Double],\n          (succ Flow..> recip Flow..> negate) 3 Test.~?= (-0.25 :: Double),\n          (negate Flow.<. recip Flow.<. succ) 3 Test.~?= (-0.25 :: Double),\n          fmap ((\\f -> f 3) . (succ Flow..>)) [recip, negate]\n            Test.~?= [0.25, -4 :: Double],\n          fmap ((\\f -> f 3) . (succ Flow..>)) [recip, negate]\n            Test.~?= [0.25, -4 :: Double],\n          fmap ((\\f -> f 3) . (Flow.<. succ)) [recip, negate]\n            Test.~?= [0.25, -4 :: Double],\n          (3 Flow.!> succ Flow.!> recip Flow.!> negate) Test.~?= (-0.25 :: Double),\n          (undefined Flow.|> const True) Test.~?= True,\n          (negate Flow.<! recip Flow.<! succ Flow.<! 3) Test.~?= (-0.25 :: Double),\n          (const True Flow.<| undefined) Test.~?= True,\n          fmap (Flow.apply' 2) [succ, recip, negate]\n            Test.~?= [3, 0.5, -2 :: Double],\n          Flow.apply undefined (const True) Test.~?= True,\n          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],\n          fmap (Flow.<! 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]\n        ]\n\n  let hasErrors = Test.errors counts /= 0\n      hasFailures = Test.failures counts /= 0\n  Monad.when (hasErrors || hasFailures) Exit.exitFailure\n"
  }
]