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
To solve this, this module provides
FreeT, which properly generalizes the
free monad to a free monad transformer which is correct by construction.
FreeT type commonly arises in coroutine and iteratee libraries that
wish to provide a monad transformer that correctly obeys the monad
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 -> ...
A free monad transformer alternates nesting the base monad
m and the base
f- The functor that generates the free monad transformer
m- The base monad
r- The type of the return value
liftF from Control.Monad.Free
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 -> ...