Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Combine reading and producing monads
import Control.Monad.Morph
import Data.Functor.Identity
-- | This function combines two different monadic effects,
-- where one of the effects is a reader effect and the other is a
-- producing effect.
-- This version results in the reader monad's inner effect to be wrapped
-- around the producing effect.
-- This requires the Reader inner effect to be an MFunctor on Identity.
-- This can enable past-Dependence.
-- Elm has foldp : (a -> state -> state) -> state -> Signal a -> Signal state
-- This is equivalent to a creating a @StateT state (Signal m) ()@
-- This function is a more general form of @StateT state (Signal m) ()@ where
-- given a reader monad to transform "a" to "c" with effects, and an "as"
-- monad that produces "a"s with other effects, run the result of "as" through
-- the reader monad to produce "c"s with both effects.
-- @
-- hoistedBind :: Monad m => m a -> (a -> (State s) c) -> StateT s m c
-- hoistedBind :: Signal STM a -> (a -> (State s) c) -> StateT state (Signal STM) c
-- hoistedBind :: Pipes.Concurrent.Input a -> (a -> (State s) c) -> StateT state Pipes.Concurrent.Input c
-- @
hoistedBind :: (Monad m, Monad (t m), MonadTrans t, MFunctor t)
=> m a -> (a -> (t Identity) c) -> t m c
hoistedBind as f = lift as >>= (hoist generalize . f)
-- | An alternate form of runReaderM where the producing effect is
-- wrapped around the reader monad's inner effect.
-- This requires the producing effect to be an MFunctor on Identity.
hoistedBind' :: (Monad m, Monad (t m), MonadTrans t, MFunctor t)
=> (t Identity) a -> (a -> m c) -> t m c
hoistedBind' as f = hoist generalize as >>= (lift . f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment