Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
People commonly misconstrue Free
as defining a monad transformer with
liftF
behaving like lift
, however that approach violates the monad
transformer laws. Another common mistake is to include the base monad as a
term in the functor, which also gives rise to an incorrect monad
transformer.
To solve this, this module provides FreeT
, which properly generalizes the
free monad to a free monad transformer which is correct by construction.
The FreeT
type commonly arises in coroutine and iteratee libraries that
wish to provide a monad transformer that correctly obeys the monad
transformer laws.
Free monad transformer
This differs substantially from the non-monad-transformer version because of the requirement to nest the constructors within the base monad.
To deconstruct a free monad transformer, use runFreeT
to unwrap it and
bind the result in the base monad. You can then pattern match against the
bound value to obtain the next constructor:
do x <- runFreeT f case x of Return r -> ... Wrap w -> ...
Because of this, you cannot create free monad transformers using the raw
constructors from FreeF
. Instead you use the smart constructors return
(from Control.Monad
) and wrap
.
A free monad transformer alternates nesting the base monad m
and the base
functor f
.
f
- The functor that generates the free monad transformerm
- The base monadr
- The type of the return value
liftF :: (Functor f, Monad m) => f r -> FreeT f m r Source #
Equivalent to liftF
from Control.Monad.Free
Free monad
The Free
type is isomorphic to the following simple implementation:
data Free f r = Return r | Wrap (f (Free f r))
... except that if you want to pattern match against those constructors, you
must first use runFree
to unwrap the value first.
case (runFreeT f) of Return r -> ... Wrap w -> ...
Similarly, you use the smart constructors return
and wrap
to build a
value of type Free
.