----------------------------------------------------------------------------- -- | -- Module : Generics.Pointless.MonadCombinators -- Copyright : (c) 2009 University of Minho -- License : BSD3 -- -- Maintainer : hpacheco@di.uminho.pt -- Stability : experimental -- Portability : non-portable -- -- Pointless Haskell: -- point-free programming with recursion patterns as hylomorphisms -- -- This module lifts many standard combinators used for point-free programming to combinators over monads. -- ----------------------------------------------------------------------------- module Generics.Pointless.MonadCombinators where import Generics.Pointless.Combinators import Control.Monad -- | The left-to-right monadic binding combinator. infixl 1 <<= (<<=) :: Monad m => (a -> m b) -> m a -> m b (<<=) f m = m >>= f -- | Higher-order monadic binding. bind :: Monad m => (a -> m b,m a) -> m b bind (f,m) = f <<= m -- | The monadic left exponentiation combinator. mlexp :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) mlexp f = curry (bind . (id >< f)) -- | The monadic right exponentiation combinator. mrexp :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) mrexp f = curry ((f <<=) . app) -- | The monadic sum combinator. infix 5 -||- (-||-) :: Monad m => (a -> m b) -> (c -> m d) -> (Either a c -> m (Either b d)) (-||-) f g = (return . inl <=< f) \/ (return . inr <=< g) -- | The strength combinator for strong monads. -- In Haskell, every monad is a strong monad: . mstrength :: Monad m => (b,m a) -> m (b,a) mstrength = uncurry (<<=) . (comp . (const return /\ dist) >< id) where dist = curry id -- | The monadic fusion combinator. -- Performs left-to-right distribution of a strong monad over a product. mfuse :: Monad m => (m a,m b) -> m (a,b) mfuse = uncurry (<<=) . (curry (mstrength . swap) >< id) . swap -- | The monadic split combinator. infix 6 /|\ (/|\) :: Monad m => (a -> m b) -> (a -> m c) -> a -> m (b,c) (/|\) f g = mfuse . (f /\ g) -- | The monadic product combinator. infix 7 >|< (>|<) :: Monad m => (a -> m c) -> (b -> m d) -> (a,b) -> m (c,d) f >|< g = f . fst /|\ g . snd