transformers: remove instance MonadFix ExceptT and ErrorT

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Tue Aug 12 23:50:04 UTC 2014


Henning Thielemann wrote:
> Am 12.08.2014 um 21:17 schrieb Edward Kmett:
> 
> >so it seems the logical extension of your request would be to strip all
> >such instances,
> 
> one by one, please :-)
> 
> Can someone provide me examples of useful applications of mfix on Maybe,
> ExceptT etc.?

I tend to agree that those MonadFix instances are not immensely useful.

As far as I can see, all one can do is a certain amount of knot-tying
on the value level on the fly. Going beyond that is prevented because
nothing is known about the return value of 'mfix f' until 'f' has run
to a successful (non-error) completion; if the success depends in any
way on the argument to 'f', the computation will bottom out.

For example, a parser for a simple language with gotos could be based on

  parseProgram :: Labels -> StateT String Maybe (Program, Labels)

where 'Labels' stores a map from label names to program locations.
Then 'mfix' can be used to feed the resulting labels right back into
'parseProgram'.

The use of 'mfix' is not essential though. In principle, one can
transform parseProgram into a function

  parseProgram' :: StateT String Maybe (Labels -> (Program, Labels))

and use an ordinary fixpoint to tie the knot. But 'mfix' buys some
convenience. (Note that this convenience comes at a fairly big cost
in the case of the list monad's 'mfix' implementation, which reruns
the whole list computation for each element of the result list.)

I think that this is basically true for all uses of 'mfix' for monads
that do not have a linear flow of computation.

> I mean, all those mfix instances contain an "error" - wouldn't it be better
> if the user would do such dirty things and insert a more specific error
> message?

If those particular error messages turn up then they indicate
programming errors: using 'mfix f' in such a way that success depends on
the argument of f, or letting the argument of 'f' escape in the case of
an unsuccessful evaluation.

So I still think that those are the right instances, even though the
error messages are not perfect.

> Admittedly, I have used mfix only once so far, at all, namely on an RWS
> monad, as far as I remember. Eventually I chose another design, because the
> mfix way was too fragile.

I've also found 'mfix' to be of limited use in practice, but there are
some cute applications, like spawning a thread, passing it its own
thread id: mfix (\tid -> forkIO (f tid)).

Cheers,

Bertram


More information about the Libraries mailing list