Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a custom monad transformer an instance of MonadError

I want to make my monad transformer to be an instance of MonadError if the transformed monad is an instance. Basically I want my transformer to behave as the built-in transformers do, for example there is a MonadError instance for StateT:

MonadError e m => MonadError e (StateT s m)

I tried doing this:

instance MonadError e m => MonadError e (MyMonadT m)

But GHC started complaining about undecidable instances, apparently the MTL library just enables undecidable instances, but is there any way to avoid that? Or it is OK in this case and it won't cause any problems?

like image 708
Marek Sapota Avatar asked Mar 30 '12 22:03

Marek Sapota


1 Answers

This is basically fine. UndecidableInstances isn't all that scary; all it means is that the compiler could, instead of finding an instance, go into an infinite loop. That sounds pretty bad, until you realise that GHC actually has a limit to the number of steps it'll take to find an instance; nothing will go wrong unless you write a bad instance, and the error messages you get will generally make it very obvious what's gone wrong.1 Certainly it's a lot less scary than things like OverlappingInstances (or worse, IncoherentInstances).

The reason it complains is because MonadError has a functional dependency from m to e. That means that the choice of m determines what e must be; i.e. every m is associated with only one e. The check for this (the Coverage Condition) is conservative, so it's easy to run into problems like this, where you try and "recurse down a level" to specify e.

1 It'll list all the instances it looked at to try and find the one it's looking for, so you'll see a bunch of repeating lines. But usually you won't even run into trouble like this in the first place.

like image 145
ehird Avatar answered Oct 01 '22 03:10

ehird