flow-1.0.1: Flow.hs
{- |
Flow is a package that provides functions and operators for writing more
understandable Haskell. It's an alternative to some common idioms like
@($)@ for function application and @(.)@ for function composition.
Flow is designed to be imported unqualified. It does not export anything
that conflicts with
<http://hackage.haskell.org/package/base the base package>.
>>> import Flow
For more information about Flow, please visit
<http://taylor.fausak.me/flow/ the official site>.
-}
module Flow (
-- * Function application
apply, (|>), (<|),
-- * Function composition
compose, (.>), (<.),
-- * Strict function application
apply', (!>), (<!),
) where
import Prelude (seq)
{- $setup
>>> import Prelude
>>> let f = (+ 2)
>>> let g = (* 2)
>>> let h = (^ 2)
-}
{- |
prop> apply x f == f x
<https://en.wikipedia.org/wiki/Function_application Function application>.
This is like the 'Prelude.$' operator.
>>> apply False not
True
Using this function with many arguments is cumbersome. Use '|>' or '<|'
instead.
>>> False `apply` not `apply` fromEnum
1
This function usually isn't necessary since @'apply' x f@ is the same as
@f x@. However it can come in handy when working with higher-order
functions.
>>> map (apply False) [not, id]
[True,False]
-}
apply :: a -> (a -> b) -> b
apply x f = f x
{- |
prop> (x |> f) == f x
prop> (x |> f |> g) == g (f x)
Left-associative 'apply' operator. This is like a flipped version of the
'Prelude.$' operator. Read it as "apply forward" or "pipe into".
>>> False |> not
True
Since this operator has such low precedence, it can be used to remove
parentheses from complicated expressions.
>>> False |> not |> fromEnum
1
This operator can be used with higher-order functions, but 'apply' might be
clearer.
>>> map (False |>) [not, id]
[True,False]
-}
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. This is like the 'Prelude.$' operator.
Read it as "apply backward" or "pipe from".
>>> not <| False
True
This operator can be used to remove parentheses from complicated
expressions because of its low precedence.
>>> fromEnum <| not <| False
1
With higher-order functions, this operator is a clearer alternative to
@flip 'apply'@.
>>> map (<| False) [not, id]
[True,False]
-}
infixr 0 <|
(<|) :: (a -> b) -> a -> b
f <| x = apply x f
{- |
prop> compose f g x == g (f x)
<https://en.wikipedia.org/wiki/Function_composition Function composition>.
This is like the 'Prelude..' operator.
>>> (compose not fromEnum) False
1
Composing many functions together quickly becomes unwieldy. Use '.>' or
'<.' instead.
>>> (not `compose` fromEnum `compose` succ) False
2
-}
compose :: (a -> b) -> (b -> c) -> (a -> c)
compose f g = \ x -> g (f x)
{- |
prop> (f .> g) x == g (f x)
prop> (f .> g .> h) x == h (g (f x))
Left-associative 'compose' operator. This is like a flipped version of the
'Prelude..' operator. Read it as "compose forward" or "and then".
>>> (not .> fromEnum) False
1
Thanks to its high precedence, composing many functions together is easy.
>>> (not .> fromEnum .> succ) False
2
-}
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. This is like the 'Prelude..'
operator. Read it as "compose backward" or "but first".
>>> (fromEnum <. not) False
1
Composing many functions together is easy thanks to its high precedence.
>>> (succ <. fromEnum <. not) False
2
-}
infixr 9 <.
(<.) :: (b -> c) -> (a -> b) -> (a -> c)
g <. f = compose f g
{- |
prop> apply' x f == seq x (f x)
Strict function application. This is like the 'Prelude.$!' operator.
>>> apply' undefined (const False)
*** Exception: Prelude.undefined
-}
apply' :: a -> (a -> b) -> b
apply' x f = seq x (apply x f)
{- |
prop> (x !> f) == seq x (f x)
prop> (x !> f !> g) == seq x (g (seq x (f x)))
Left-associative 'apply'' operator. This is like a flipped version of the
'Prelude.$!' operator.
>>> undefined !> const False
*** 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) == seq x (g (seq x (f x)))
Right-associative 'apply'' operator. This is like the 'Prelude.$!'
operator.
>>> const False <! undefined
*** Exception: Prelude.undefined
-}
infixr 0 <!
(<!) :: (a -> b) -> a -> b
f <! x = apply' x f