packages feed

flow 1.0.4 → 1.0.5

raw patch · 3 files changed

+234/−2 lines, 3 files

Files

+ Flow.hs view
@@ -0,0 +1,226 @@+{- |+    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)++{- $setup+    >>> import Prelude+    >>> let f = (+ 3)+    >>> let g = (* 3)+    >>> let h = (^ 3)+-}++{- |+    prop> (x |> f) == f x++    prop> (x |> f |> g) == g (f x)++    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.&').+-}+infixl 0 |>+(|>) :: a -> (a -> b) -> b+x |> f = apply x f++{- |+    prop> (f <| x) == f x++    prop> (g <| f <| x) == g (f x)++    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.$').+-}+infixr 0 <|+(<|) :: (a -> b) -> a -> b+f <| x = apply x f++{- |+    prop> apply x f == f x++    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]+-}+apply :: a -> (a -> b) -> b+apply x f = f x++{- |+    prop> (f .> g) x == g (f x)++    prop> (f .> g .> h) x == h (g (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.>>>').+-}+infixl 9 .>+(.>) :: (a -> b) -> (b -> c) -> (a -> c)+f .> g = compose f g++{- |+    prop> (g <. f) x == g (f x)++    prop> (h <. g <. f) x == h (g (f x))++    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..').+-}+infixr 9 <.+(<.) :: (b -> c) -> (a -> b) -> (a -> c)+g <. f = compose f g++{- |+    prop> compose f g x == g (f x)++    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]+-}+compose :: (a -> b) -> (b -> c) -> (a -> c)+compose f g = \ x -> g (f x)++{- |+    prop> (x !> f) == seq x (f x)++    prop> (x !> f !> g) == let y = seq x (f x) in seq y (g y)++    Left-associative 'apply'' operator. Read as "strict apply forward" or+    "strict pipe info". 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+-}+infixl 0 !>+(!>) :: a -> (a -> b) -> b+x !> f = apply' x f++{- |+    prop> (f <! x) == seq x (f x)++    prop> (g <! f <! x) == let y = seq x (f x) in seq y (g y)++    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+-}+infixr 0 <!+(<!) :: (a -> b) -> a -> b+f <! x = apply' x f++{- |+    prop> apply' x f == seq x (f x)++    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+-}+apply' :: a -> (a -> b) -> b+apply' x f = seq x (apply x f)
flow.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           flow-version:        1.0.4+version:        1.0.5 synopsis:       Write more understandable Haskell. description:    Flow provides operators for writing more understandable Haskell. category:       Combinators, Functions, Utility@@ -29,6 +29,10 @@   ghc-options: -Wall   build-depends:       base <5+  exposed-modules:+      Flow+  other-modules:+      Paths_flow   default-language: Haskell2010  test-suite flow-test-suite
package.yaml view
@@ -12,6 +12,8 @@ library:   dependencies:   - base <5+  exposed-modules:+  - Flow license: MIT maintainer: Taylor Fausak name: flow@@ -25,4 +27,4 @@     - QuickCheck ==2.*     - template-haskell ==2.*     main: FlowTest.hs-version: '1.0.4'+version: '1.0.5'