Closed fizruk closed 10 years ago
Apparantly, forall m. Monad m => t m a
gives way more flexibility than MFunctor t => t Identity a
.
The reason is that ContT
is not actually MFunctor
(because m r
in (a -> m r) -> m r
is in both positive and negative positions), so one cannot turn ContT Identity a
into a ContT m a
, unless m
is isomorphic to Identity
.
After thinking a bit more on this, I've managed to avoid MFunctor
and forall
ed iterM
in my code.
This is what I use now:
transform :: (Functor f, Monad m, MonadTrans t, Monad (t m))
=> (f (t m a) -> t m a) -> FreeT f m a -> t m a
transform phi = iterT phi . hoistIterT lift
runT :: (Functor f, MonadFree f m, MonadTrans t, Monad (t m))
=> FreeT f (t m) a -> t m a
runT = iterT wrapT
transform
is now merged in #42 as iterTM
, so I close this issue.
For
Free
monad we haveiterM
that makes it easy to write arbitrary interpreters for the underlying functor. ForFreeT
we haveiterT
which is more likeiter
: we can't introduce an arbitrary monad and are forced to use the underlying one.The problem with implementing
iterM'
forFreeT
is that monads are not (easily) composable. But monad transformers are! This gave me the idea thatiterM'
should acceptFreeT f (t Identity) a
or(forall m. Monad m => FreeT f (t m) a
as a second argument instead ofFreeT f m a
.Using
hoist
frommmorph
packageiterM'
can be implemented like this:Note the similarity with
iterM
implementation:I believe this similarity suggests I'm on the right way at least.
Without any extra dependencies (e.g.
mmorph
)iterM'
can be alternatively defined as follows:But that last definition forces users to write values of higher rank types.
So I suggest to add
iterM'
(perhaps with a better name) to the library.