functor-monadic-0.1.0.1: Data/Functor/Monadic.hs
-- |Helper functions for functors.
--
-- These operators are designed to make the interoperation between monadic
-- and pure computations more convenient by allowing them to be chained together
-- without peppering the program with superflouos return statements.
--
-- Each function is a pure analogue of a monadic one. The correspondences are
-- as follows:
--
-- * @>$> ~ >>=@ (bind)
-- * @$> ~ >> @ (throw away left argument)
-- * @<$ ~ << @ (re-exported from "Data.Functor")
-- * @<$< ~ =<< @ (same as 'Data.Functor.<$>', but with the precedence of '>>=')
-- * @>=$> ~ >=> @ (Kleisli composition)
-- * @<$=< ~ <=< @ (flipped Kleisli composition)
--
-- Lastly, '|>' is left-to-right function composition (flipped version of '$').
module Data.Functor.Monadic (
module Data.Functor,
(>$>),
($>),
(<$<),
(>=$>),
(<$=<),
(|>)) where
import Data.Functor ((<$))
infixl 1 >$>
infixl 1 $>
infixr 1 <$<
infixl 1 >=$>
infixr 1 <$=<
infixl 1 |>
-- |Flipped 'fmap' for chaining plain functions after a functor in the following
-- way:
--
-- @
-- readFile '1.txt' >$> lines >$> map length >>= print
-- @
--
-- @lines@ and @map length@ are non-monadic functions, but peppering
-- them with returns, as pure '>>=' necessitates, is quite tedious.
--
-- In general:
--
-- @
-- m >>= return . f is the same as m >$> f
-- @
(>$>) :: Functor f => f a -> (a -> b) -> f b
(>$>) = flip fmap
-- |Left-associatiative, flipped '$>'. Corresponds to '>>'
($>) :: Functor f => f b -> a -> f a
($>) = flip (<$)
-- |Right-associative infix synonym for 'fmap'.
(<$<) :: Functor f => (a -> b) -> f a -> f b
(<$<) = fmap
-- |Application of '>$>' to Kleisli composition 'Control.Monad.>=>'
-- Use is analogous to that of '>$>', e.g.
--
-- @
-- f :: FilePath -> IO ()
-- f = (readFile >=$> lines >=$> map length >=> print)
-- @
--
-- In general:
--
-- @
-- m >=$> f is the same as m >=> return . f
-- @
(>=$>) :: Functor f => (a -> f b) -> (b -> c) -> a -> f c
(>=$>) f g x = f x >$> g
-- |Flipped version of '>=$>'.
(<$=<) :: Functor f => (b -> c) -> (a -> f b) -> a -> f c
(<$=<) = flip (>=$>)
-- |Flipped version of '$'.
(|>) :: a -> (a -> b) -> b
(|>) = flip ($)