packages feed

flow 1.0.22 → 2.0.0.11

raw patch · 10 files changed

Files

+ CHANGELOG.md view
@@ -0,0 +1,4 @@+# Change log++Flow follows the [Package Versioning Policy](https://pvp.haskell.org).+You can find release notes [on GitHub](https://github.com/tfausak/flow/releases).
− LICENSE.markdown
@@ -1,21 +0,0 @@-MIT License--Copyright (c) 2021 Taylor Fausak--Permission is hereby granted, free of charge, to any person obtaining a copy-of this software and associated documentation files (the "Software"), to deal-in the Software without restriction, including without limitation the rights-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-copies of the Software, and to permit persons to whom the Software is-furnished to do so, subject to the following conditions:--The above copyright notice and this permission notice shall be included in all-copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-SOFTWARE.
+ LICENSE.txt view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2026 Taylor Fausak++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
− README.markdown
@@ -1,80 +0,0 @@-# [Flow][]--[![CI](https://github.com/tfausak/flow/workflows/CI/badge.svg)](https://github.com/tfausak/flow/actions/new)-[![Hackage](https://img.shields.io/hackage/v/flow)](https://hackage.haskell.org/package/flow)-[![Stackage](https://www.stackage.org/package/flow/badge/nightly?label=stackage)](https://www.stackage.org/package/flow)--Write more understandable Haskell.--Flow is a package that provides functions and operators for writing more-understandable Haskell. It is an alternative to some common idioms like-[`($)`][] for function application and [`(.)`][] for function composition.---   [Requirements](#requirements)--   [Installation](#installation)--   [Usage](#usage)-    -   [Cheat sheet](#cheat-sheet)--## Requirements--Flow requires a Haskell compiler. It is tested with recent versions of GHC, but-older or different compilers should be acceptable. For installation with Cabal,-Flow requires at least Cabal 1.8.--## Installation--To add Flow as a dependency to your package, add it to your Cabal file.--```-build-depends: flow ==1.0.*-```--## Usage--Flow is designed to be imported unqualified. It does not export anything that-conflicts with [the base package][].--``` hs-import Flow-```--### Cheat sheet--Flow            | Base---------------- | --------------<code>x &#124;> f</code> | `x & f`-<code>f <&#124; x</code> | `f $ x`-`apply x f`     | `f x`-`f .> g`        | `f >>> g`-`g <. f`        | `g . f`-`compose f g x` | `g (f x)`-`x !> f`        | --`f <! x`        | `f $! x`-`apply' x f`    | `seq x (f x)`--### Converting existing code--If you want to uniformly use flow operators you can use [HLint] with the-`hlint-flow.yaml` file. For easy use, it is best to extract the-`hlint-flow.yaml` to your project directory and do--``` sh-> hlint -h hlint-flow.yaml <source file>-```--or--``` sh-> hlint --git -h hlint-flow.yaml-```--to check all Haskell source tracked by git.--For more information about Flow, please read [the Haddock documentation][].--[HLint]: https://github.com/ndmitchell/hlint-[Flow]: http://taylor.fausak.me/flow/-[`($)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:-36--[`(.)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:.-[the base package]: http://hackage.haskell.org/package/base-[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html
+ README.md view
@@ -0,0 +1,79 @@+# [Flow][]++[![CI](https://github.com/tfausak/flow/actions/workflows/ci.yml/badge.svg)](https://github.com/tfausak/flow/actions/workflows/ci.yml)+[![Hackage](https://badgen.net/hackage/v/flow)](https://hackage.haskell.org/package/flow)++Write more understandable Haskell.++Flow is a package that provides functions and operators for writing more+understandable Haskell. It is an alternative to some common idioms like+[`($)`][] for function application and [`(.)`][] for function composition.++-   [Requirements](#requirements)+-   [Installation](#installation)+-   [Usage](#usage)+    -   [Cheat sheet](#cheat-sheet)++## Requirements++Flow requires a Haskell compiler. It is tested with recent versions of GHC, but+older or different compilers should be acceptable. For installation with Cabal,+Flow requires at least Cabal 2.2.++## Installation++To add Flow as a dependency to your package, add it to your Cabal file.++```+build-depends: flow ==2.0.*+```++## Usage++Flow is designed to be imported unqualified. It does not export anything that+conflicts with [the base package][].++``` hs+import Flow+```++### Cheat sheet++Flow            | Base+--------------- | -------------+<code>x &#124;> f</code> | `x & f`+<code>f <&#124; x</code> | `f $ x`+`apply x f`     | `f x`+`f .> g`        | `f >>> g`+`g <. f`        | `g . f`+`compose f g x` | `g (f x)`+`x !> f`        | -+`f <! x`        | `f $! x`+`apply' x f`    | `seq x (f x)`++### Converting existing code++If you want to uniformly use flow operators you can use [HLint] with the+`hlint-flow.yaml` file. For easy use, it is best to extract the+`hlint-flow.yaml` to your project directory and do++``` sh+> hlint -h hlint-flow.yaml <source file>+```++or++``` sh+> hlint --git -h hlint-flow.yaml+```++to check all Haskell source tracked by git.++For more information about Flow, please read [the Haddock documentation][].++[HLint]: https://github.com/ndmitchell/hlint+[Flow]: http://taylor.fausak.me/flow/+[`($)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:-36-+[`(.)`]: http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#v:.+[the base package]: http://hackage.haskell.org/package/base+[the haddock documentation]: https://hackage.haskell.org/package/flow/docs/Flow.html
flow.cabal view
@@ -1,15 +1,15 @@-cabal-version: >= 1.10-+cabal-version: 2.2 name: flow-version: 1.0.22-+version: 2.0.0.11 synopsis: Write more understandable Haskell. description: Flow provides operators for writing more understandable Haskell.- build-type: Simple category: Combinators, Functions, Utility-extra-source-files: README.markdown-license-file: LICENSE.markdown+extra-doc-files:+  CHANGELOG.md+  README.md++license-file: LICENSE.txt license: MIT maintainer: Taylor Fausak @@ -17,27 +17,44 @@   location: https://github.com/tfausak/flow   type: git -library-  build-depends:-    base >= 4.13.0 && < 4.16+flag pedantic+  default: False+  description: Enables @-Werror@, which turns warnings into errors.+  manual: True++common library+  build-depends: base ^>=4.20.0.0 || ^>=4.21.0.0 || ^>=4.22.0.0   default-language: Haskell2010-  exposed-modules: Flow   ghc-options:     -Weverything+    -Wno-all-missed-specialisations+    -Wno-implicit-prelude     -Wno-missing-exported-signatures+    -Wno-missing-safe-haskell-mode+    -Wno-prepositive-qualified-module     -Wno-safe-  hs-source-dirs: src/lib -  if impl(ghc >= 8.10)-    ghc-options:-      -Wno-missing-safe-haskell-mode+  if flag(pedantic)+    ghc-options: -Werror -test-suite test+common executable+  import: library+  build-depends: flow+  ghc-options:+    -rtsopts+    -threaded++library+  import: library+  -- cabal-gild: discover source/library+  exposed-modules: Flow+  hs-source-dirs: source/library++test-suite flow-test-suite+  import: executable   build-depends:-    base -any-    , flow -any-    , HUnit >= 1.6.1 && < 1.7-  default-language: Haskell2010-  hs-source-dirs: src/test+    HUnit ^>=1.6.2.0++  hs-source-dirs: source/test-suite   main-is: Main.hs   type: exitcode-stdio-1.0
+ source/library/Flow.hs view
@@ -0,0 +1,273 @@+-- | Flow provides operators for writing more understandable Haskell. It is an+-- alternative to some common idioms like ('Prelude.$') for function+-- application and ('Prelude..') for function composition.+--+-- Flow is designed to be imported unqualified. It does not export anything+-- that conflicts with the base package.+--+-- >>> import Flow+--+-- == Rationale+--+-- I think that Haskell can be hard to read. It has two operators for applying+-- functions. Both are not really necessary and only serve to reduce+-- parentheses. But they make code hard to read. People who do not already+-- know Haskell have no chance of guessing what @foo $ bar@ or @baz & qux@+-- mean.+--+-- Those that do know Haskell are forced to read lines forwards and backwards+-- at the same time, thanks to function composition. Even something simple,+-- like finding the minimum element, bounces around: @f = head . sort@.+--+-- I think we can do better. By using directional operators, we can allow+-- readers to move their eye in only one direction, be that left-to-right or+-- right-to-left. And by using idioms common in other programming languages,+-- we can allow people who aren't familiar with Haskell to guess at the+-- meaning.+--+-- So instead of ('Prelude.$'), I propose ('<|'). It is a pipe, which anyone+-- who has touched a Unix system should be familiar with. And it points in the+-- direction it sends arguments along. Similarly, replace ('Data.Function.&')+-- with ('|>'). And for composition, ('<.') replaces ('Prelude..'). I would+-- have preferred @<<@, but its counterpart @>>@ is taken by Haskell's syntax.+-- So-called "backwards" composition is normally expressed with+-- ('Control.Category.>>>'), which Flow provides as ('.>').+module Flow+  ( -- * Function application+    (|>),+    (<|),+    apply,++    -- * Function composition+    (.>),+    (<.),+    compose,++    -- * Strict function application+    (!>),+    (<!),+    apply',+  )+where++import qualified Prelude++-- | Left-associative 'apply' operator. Read as "apply forward" or "pipe into".+-- Use this to create long chains of computation that suggest which direction+-- things move in.+--+-- >>> 3 |> succ |> recip |> negate+-- -0.25+--+-- Or use it anywhere you would use ('Data.Function.&').+--+-- prop> \ x -> (x |> f) == f x+--+-- prop> \ x -> (x |> f |> g) == g (f x)+infixl 0 |>++{-# INLINE (|>) #-}+(|>) :: a -> (a -> b) -> b+(|>) = apply++-- | Right-associative 'apply' operator. Read as "apply backward" or "pipe+-- from". Use this to create long chains of computation that suggest which+-- direction things move in. You may prefer this operator over ('|>') for+-- 'Prelude.IO' actions since it puts the last function first.+--+-- >>> print <| negate <| recip <| succ <| 3+-- -0.25+--+-- Or use it anywhere you would use ('Prelude.$').+--+-- Note that ('<|') and ('|>') have the same precedence, so they cannot be used+-- together.+--+-- >>> -- This doesn't work!+-- >>> -- print <| 3 |> succ |> recip |> negate+--+-- prop> \ x -> (f <| x) == f x+--+-- prop> \ x -> (g <| f <| x) == g (f x)+infixr 0 <|++{-# INLINE (<|) #-}+(<|) :: (a -> b) -> a -> b+(<|) f = f++-- | Function application. This function usually isn't necessary, but it can be+-- more readable than some alternatives when used with higher-order functions+-- like 'Prelude.map'.+--+-- >>> map (apply 2) [succ, recip, negate]+-- [3.0,0.5,-2.0]+--+-- In general you should prefer using an explicit lambda or operator section.+--+-- >>> map (\ f -> 2 |> f) [succ, recip, negate]+-- [3.0,0.5,-2.0]+-- >>> map (2 |>) [succ, recip, negate]+-- [3.0,0.5,-2.0]+-- >>> map (<| 2) [succ, recip, negate]+-- [3.0,0.5,-2.0]+--+-- prop> \ x -> apply x f == f x+{-# INLINE apply #-}+apply :: a -> (a -> b) -> b+apply x f = f x++-- | Left-associative 'compose' operator. Read as "compose forward" or "and+-- then". Use this to create long chains of computation that suggest which+-- direction things move in.+--+-- >>> let f = succ .> recip .> negate+-- >>> f 3+-- -0.25+--+-- Or use it anywhere you would use ('Control.Category.>>>').+--+-- prop> \ x -> (f .> g) x == g (f x)+--+-- prop> \ x -> (f .> g .> h) x == h (g (f x))+infixl 9 .>++{-# INLINE (.>) #-}+(.>) :: (a -> b) -> (b -> c) -> (a -> c)+f .> g = compose f g++-- | Right-associative 'compose' operator. Read as "compose backward" or "but+-- first". Use this to create long chains of computation that suggest which+-- direction things move in. You may prefer this operator over ('.>') for+-- 'Prelude.IO' actions since it puts the last function first.+--+-- >>> let f = print <. negate <. recip <. succ+-- >>> f 3+-- -0.25+--+-- Or use it anywhere you would use ('Prelude..').+--+-- Note that ('<.') and ('.>') have the same precedence, so they cannot be used+-- together.+--+-- >>> -- This doesn't work!+-- >>> -- print <. succ .> recip .> negate+--+-- prop> \ x -> (g <. f) x == g (f x)+--+-- prop> \ x -> (h <. g <. f) x == h (g (f x))+infixr 9 <.++{-# INLINE (<.) #-}+(<.) :: (b -> c) -> (a -> b) -> (a -> c)+g <. f = compose f g++-- | Function composition. This function usually isn't necessary, but it can be+-- more readable than some alternatives when used with higher-order functions+-- like 'Prelude.map'.+--+-- >>> let fs = map (compose succ) [recip, negate]+-- >>> map (apply 3) fs+-- [0.25,-4.0]+--+-- In general you should prefer using an explicit lambda or operator section.+--+-- >>> map (\ f -> f 3) (map (\ f -> succ .> f) [recip, negate])+-- [0.25,-4.0]+-- >>> map (\ f -> f 3) (map (succ .>) [recip, negate])+-- [0.25,-4.0]+-- >>> map (\ f -> f 3) (map (<. succ) [recip, negate])+-- [0.25,-4.0]+--+-- prop> \ x -> compose f g x == g (f x)+{-# INLINE compose #-}+compose :: (a -> b) -> (b -> c) -> (a -> c)+compose f g = \x -> g (f x)++-- | Left-associative 'apply'' operator. Read as "strict apply forward" or+-- "strict pipe into". Use this to create long chains of computation that+-- suggest which direction things move in.+--+-- >>> 3 !> succ !> recip !> negate+-- -0.25+--+-- The difference between this and ('|>') is that this evaluates its argument+-- before passing it to the function.+--+-- >>> undefined |> const True+-- True+-- >>> undefined !> const True+-- *** Exception: Prelude.undefined+-- ...+--+-- prop> \ x -> (x !> f) == seq x (f x)+--+-- prop> \ x -> (x !> f !> g) == let y = seq x (f x) in seq y (g y)+infixl 0 !>++{-# INLINE (!>) #-}+(!>) :: a -> (a -> b) -> b+(!>) = \x f -> f <! x++-- | Right-associative 'apply'' operator. Read as "strict apply backward" or+-- "strict pipe from". Use this to create long chains of computation that+-- suggest which direction things move in. You may prefer this operator over+-- ('!>') for 'Prelude.IO' actions since it puts the last function first.+--+-- >>> print <! negate <! recip <! succ <! 3+-- -0.25+--+-- Or use it anywhere you would use ('Prelude.$!').+--+-- The difference between this and ('<|') is that this evaluates its argument+-- before passing it to the function.+--+-- >>> const True <| undefined+-- True+-- >>> const True <! undefined+-- *** Exception: Prelude.undefined+-- ...+--+-- Note that ('<!') and ('!>') have the same precedence, so they cannot be used+-- together.+--+-- >>> -- This doesn't work!+-- >>> -- print <! 3 !> succ !> recip !> negate+--+-- prop> \ x -> (f <! x) == seq x (f x)+--+-- prop> \ x -> (g <! f <! x) == let y = seq x (f x) in seq y (g y)+infixr 0 <!++{-# INLINE (<!) #-}+(<!) :: (a -> b) -> a -> b+(<!) = (Prelude.$!)++-- | Strict function application. This function usually isn't necessary, but it+-- can be more readable than some alternatives when used with higher-order+-- functions like 'Prelude.map'.+--+-- >>> map (apply' 2) [succ, recip, negate]+-- [3.0,0.5,-2.0]+--+-- The different between this and 'apply' is that this evaluates its argument+-- before passing it to the function.+--+-- >>> apply undefined (const True)+-- True+-- >>> apply' undefined (const True)+-- *** Exception: Prelude.undefined+-- ...+--+-- In general you should prefer using an explicit lambda or operator section.+--+-- >>> map (\ f -> 2 !> f) [succ, recip, negate]+-- [3.0,0.5,-2.0]+-- >>> map (2 !>) [succ, recip, negate]+-- [3.0,0.5,-2.0]+-- >>> map (<! 2) [succ, recip, negate]+-- [3.0,0.5,-2.0]+--+-- prop> \ x -> apply' x f == seq x (f x)+{-# INLINE apply' #-}+apply' :: a -> (a -> b) -> b+apply' = (!>)
+ source/test-suite/Main.hs view
@@ -0,0 +1,42 @@+import qualified Control.Monad as Monad+import qualified Flow+import qualified System.Exit as Exit+import qualified Test.HUnit as Test++main :: IO ()+main = do+  counts <-+    Test.runTestTT $+      Test.TestList+        [ True Test.~?= True,+          (3 Flow.|> succ Flow.|> recip Flow.|> negate) Test.~?= (-0.25 :: Double),+          (negate Flow.<| recip Flow.<| succ Flow.<| 3) Test.~?= (-0.25 :: Double),+          fmap (Flow.apply 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (Flow.<| 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (Flow.apply 3 . Flow.compose succ) [recip, negate]+            Test.~?= [0.25, -4 :: Double],+          (succ Flow..> recip Flow..> negate) 3 Test.~?= (-0.25 :: Double),+          (negate Flow.<. recip Flow.<. succ) 3 Test.~?= (-0.25 :: Double),+          fmap ((\f -> f 3) . (succ Flow..>)) [recip, negate]+            Test.~?= [0.25, -4 :: Double],+          fmap ((\f -> f 3) . (succ Flow..>)) [recip, negate]+            Test.~?= [0.25, -4 :: Double],+          fmap ((\f -> f 3) . (Flow.<. succ)) [recip, negate]+            Test.~?= [0.25, -4 :: Double],+          (3 Flow.!> succ Flow.!> recip Flow.!> negate) Test.~?= (-0.25 :: Double),+          (undefined Flow.|> const True) Test.~?= True,+          (negate Flow.<! recip Flow.<! succ Flow.<! 3) Test.~?= (-0.25 :: Double),+          (const True Flow.<| undefined) Test.~?= True,+          fmap (Flow.apply' 2) [succ, recip, negate]+            Test.~?= [3, 0.5, -2 :: Double],+          Flow.apply undefined (const True) Test.~?= True,+          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double],+          fmap (Flow.<! 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]+        ]++  let hasErrors = Test.errors counts /= 0+      hasFailures = Test.failures counts /= 0+  Monad.when (hasErrors || hasFailures) Exit.exitFailure
− src/lib/Flow.hs
@@ -1,247 +0,0 @@--- | Flow provides operators for writing more understandable Haskell. It is an--- alternative to some common idioms like ('Prelude.$') for function--- application and ('Prelude..') for function composition.------ Flow is designed to be imported unqualified. It does not export anything--- that conflicts with the base package.------ >>> import Flow------ == Rationale------ I think that Haskell can be hard to read. It has two operators for applying--- functions. Both are not really necessary and only serve to reduce--- parentheses. But they make code hard to read. People who do not already--- know Haskell have no chance of guessing what @foo $ bar@ or @baz & qux@--- mean.------ Those that do know Haskell are forced to read lines forwards and backwards--- at the same time, thanks to function composition. Even something simple,--- like finding the minimum element, bounces around: @f = head . sort@.------ I think we can do better. By using directional operators, we can allow--- readers to move their eye in only one direction, be that left-to-right or--- right-to-left. And by using idioms common in other programming languages,--- we can allow people who aren't familiar with Haskell to guess at the--- meaning.------ So instead of ('Prelude.$'), I propose ('<|'). It is a pipe, which anyone--- who has touched a Unix system should be familiar with. And it points in the--- direction it sends arguments along. Similarly, replace ('Prelude.&') with--- ('|>'). And for composition, ('<.') replaces ('Prelude..'). I would have--- preferred @<<@, but its counterpart @>>@ is taken by Haskell's syntax.--- So-called "backwards" composition is normally expressed with--- ('Control.Category.>>>'), which Flow provides as ('.>').-module Flow (-    -- * Function application-    (|>), (<|), apply,-    -- * Function composition-    (.>), (<.), compose,-    -- * Strict function application-    (!>), (<!), apply',-) where--import Prelude (seq)---- | Left-associative 'apply' operator. Read as "apply forward" or "pipe into".--- Use this to create long chains of computation that suggest which direction--- things move in.------ >>> 3 |> succ |> recip |> negate--- -0.25------ Or use it anywhere you would use ('Prelude.&').------ prop> \ x -> (x |> f) == f x------ prop> \ x -> (x |> f |> g) == g (f x)-infixl 0 |>-(|>) :: a -> (a -> b) -> b-x |> f = apply x f---- | Right-associative 'apply' operator. Read as "apply backward" or "pipe--- from". Use this to create long chains of computation that suggest which--- direction things move in. You may prefer this operator over ('|>') for--- 'Prelude.IO' actions since it puts the last function first.------ >>> print <| negate <| recip <| succ <| 3--- -0.25------ Or use it anywhere you would use ('Prelude.$').------ Note that ('<|') and ('|>') have the same precedence, so they cannot be used--- together.------ >>> -- This doesn't work!--- >>> -- print <| 3 |> succ |> recip |> negate------ prop> \ x -> (f <| x) == f x------ prop> \ x -> (g <| f <| x) == g (f x)-infixr 0 <|-(<|) :: (a -> b) -> a -> b-f <| x = apply x f---- | Function application. This function usually isn't necessary, but it can be--- more readable than some alternatives when used with higher-order functions--- like 'Prelude.map'.------ >>> map (apply 2) [succ, recip, negate]--- [3.0,0.5,-2.0]------ In general you should prefer using an explicit lambda or operator section.------ >>> map (\ f -> 2 |> f) [succ, recip, negate]--- [3.0,0.5,-2.0]--- >>> map (2 |>) [succ, recip, negate]--- [3.0,0.5,-2.0]--- >>> map (<| 2) [succ, recip, negate]--- [3.0,0.5,-2.0]------ prop> \ x -> apply x f == f x-apply :: a -> (a -> b) -> b-apply x f = f x---- | Left-associative 'compose' operator. Read as "compose forward" or "and--- then". Use this to create long chains of computation that suggest which--- direction things move in.------ >>> let f = succ .> recip .> negate--- >>> f 3--- -0.25------ Or use it anywhere you would use ('Control.Category.>>>').------ prop> \ x -> (f .> g) x == g (f x)------ prop> \ x -> (f .> g .> h) x == h (g (f x))-infixl 9 .>-(.>) :: (a -> b) -> (b -> c) -> (a -> c)-f .> g = compose f g---- | Right-associative 'compose' operator. Read as "compose backward" or "but--- first". Use this to create long chains of computation that suggest which--- direction things move in. You may prefer this operator over ('.>') for--- 'Prelude.IO' actions since it puts the last function first.------ >>> let f = print <. negate <. recip <. succ--- >>> f 3--- -0.25------ Or use it anywhere you would use ('Prelude..').------ Note that ('<.') and ('.>') have the same precedence, so they cannot be used--- together.------ >>> -- This doesn't work!--- >>> -- print <. succ .> recip .> negate------ prop> \ x -> (g <. f) x == g (f x)------ prop> \ x -> (h <. g <. f) x == h (g (f x))-infixr 9 <.-(<.) :: (b -> c) -> (a -> b) -> (a -> c)-g <. f = compose f g---- | Function composition. This function usually isn't necessary, but it can be--- more readable than some alternatives when used with higher-order functions--- like 'Prelude.map'.------ >>> let fs = map (compose succ) [recip, negate]--- >>> map (apply 3) fs--- [0.25,-4.0]------ In general you should prefer using an explicit lambda or operator section.------ >>> map (\ f -> f 3) (map (\ f -> succ .> f) [recip, negate])--- [0.25,-4.0]--- >>> map (\ f -> f 3) (map (succ .>) [recip, negate])--- [0.25,-4.0]--- >>> map (\ f -> f 3) (map (<. succ) [recip, negate])--- [0.25,-4.0]------ prop> \ x -> compose f g x == g (f x)-compose :: (a -> b) -> (b -> c) -> (a -> c)-compose f g = \ x -> g (f x)---- | Left-associative 'apply'' operator. Read as "strict apply forward" or--- "strict pipe into". Use this to create long chains of computation that--- suggest which direction things move in.------ >>> 3 !> succ !> recip !> negate--- -0.25------ The difference between this and ('|>') is that this evaluates its argument--- before passing it to the function.------ >>> undefined |> const True--- True--- >>> undefined !> const True--- *** Exception: Prelude.undefined--- ...------ prop> \ x -> (x !> f) == seq x (f x)------ prop> \ x -> (x !> f !> g) == let y = seq x (f x) in seq y (g y)-infixl 0 !>-(!>) :: a -> (a -> b) -> b-x !> f = apply' x f---- | Right-associative 'apply'' operator. Read as "strict apply backward" or--- "strict pipe from". Use this to create long chains of computation that--- suggest which direction things move in. You may prefer this operator over--- ('!>') for 'Prelude.IO' actions since it puts the last function first.------ >>> print <! negate <! recip <! succ <! 3--- -0.25------ The difference between this and ('<|') is that this evaluates its argument--- before passing it to the function.------ >>> const True <| undefined--- True--- >>> const True <! undefined--- *** Exception: Prelude.undefined--- ...------ Note that ('<!') and ('!>') have the same precedence, so they cannot be used--- together.------ >>> -- This doesn't work!--- >>> -- print <! 3 !> succ !> recip !> negate------ prop> \ x -> (f <! x) == seq x (f x)------ prop> \ x -> (g <! f <! x) == let y = seq x (f x) in seq y (g y)-infixr 0 <!-(<!) :: (a -> b) -> a -> b-f <! x = apply' x f---- | Strict function application. This function usually isn't necessary, but it--- can be more readable than some alternatives when used with higher-order--- functions like 'Prelude.map'.------ >>> map (apply' 2) [succ, recip, negate]--- [3.0,0.5,-2.0]------ The different between this and 'apply' is that this evaluates its argument--- before passing it to the function.------ >>> apply undefined (const True)--- True--- >>> apply' undefined (const True)--- *** Exception: Prelude.undefined--- ...------ In general you should prefer using an explicit lambda or operator section.------ >>> map (\ f -> 2 !> f) [succ, recip, negate]--- [3.0,0.5,-2.0]--- >>> map (2 !>) [succ, recip, negate]--- [3.0,0.5,-2.0]--- >>> map (<! 2) [succ, recip, negate]--- [3.0,0.5,-2.0]------ prop> \ x -> apply' x f == seq x (f x)-apply' :: a -> (a -> b) -> b-apply' x f = seq x (apply x f)
− src/test/Main.hs
@@ -1,36 +0,0 @@-import qualified Control.Monad as Monad-import qualified Flow-import qualified System.Exit as Exit-import qualified Test.HUnit as Test--main :: IO ()-main = do-  counts <- Test.runTestTT $ Test.TestList-    [ True Test.~?= True-    , (3 Flow.|> succ Flow.|> recip Flow.|> negate) Test.~?= (-0.25 :: Double)-    , (negate Flow.<| recip Flow.<| succ Flow.<| 3) Test.~?= (-0.25 :: Double)-    , map (Flow.apply 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (\ f -> 2 Flow.|> f) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (2 Flow.|>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (Flow.<| 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (Flow.apply 3) (map (Flow.compose succ) [recip, negate]) Test.~?= [0.25, -4 :: Double]-    , (succ Flow..> recip Flow..> negate) 3 Test.~?= (-0.25 :: Double)-    , (negate Flow.<. recip Flow.<. succ) 3 Test.~?= (-0.25 :: Double)-    , map (\ f -> f 3) (map (\ f -> succ Flow..> f) [recip, negate]) Test.~?= [0.25, -4 :: Double]-    , map (\ f -> f 3) (map (succ Flow..>) [recip, negate]) Test.~?= [0.25, -4 :: Double]-    , map (\ f -> f 3) (map (Flow.<. succ) [recip, negate]) Test.~?= [0.25, -4 :: Double]-    , (3 Flow.!> succ Flow.!> recip Flow.!> negate) Test.~?= (-0.25 :: Double)-    , (undefined Flow.|> const True) Test.~?= True-    , (negate Flow.<! recip Flow.<! succ Flow.<! 3) Test.~?= (-0.25 :: Double)-    , (const True Flow.<| undefined) Test.~?= True-    , map (Flow.apply' 2) [succ, recip, negate]  Test.~?= [3, 0.5, -2 :: Double]-    , Flow.apply undefined (const True) Test.~?= True-    , map (\ f -> 2 Flow.!> f) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (2 Flow.!>) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    , map (Flow.<! 2) [succ, recip, negate] Test.~?= [3, 0.5, -2 :: Double]-    ]--  let-    hasErrors = Test.errors counts /= 0-    hasFailures = Test.failures counts /= 0-  Monad.when (hasErrors || hasFailures) Exit.exitFailure