blame: mtl MonadReader instance for ContT

Henning Thielemann schlepptop at
Tue Dec 23 16:37:07 EST 2008

Nicolas Frisby schrieb:
> This mtl instance is in conflict with a usage of shift/reset that I'm
> porting from ML (Sheard's type-directed partial evaluator).
>> instance (MonadReader r' m) => MonadReader r' (ContT r m) where
>>     local f m = ContT $ \c -> do
>>         r <- ask
>>         local f (runContT m (local (const r) . c))
> I need to remove the "local (const r)" bit. I think this is just a
> different point in the diverse design space of dynamic
> binding/delimited control. Since Haskell lacks visibility management
> for importing instances, I'm forced to duplicate the rest of the ContT
> code in order to replace this instance with my own.

You may define a newtype, lift all required instances with
-XGeneralizedNewtypeDeriving and define your own MonadReader instance.

> 1) I am hoping this list can recall the reason for putting this design
> decision into the mtl. Perhaps there's a reason to prefer this
> particular side-effect interaction.
> 2) I am suggesting that the mtl be restructured such that this
> instance be delegated to a separate module so that
>       i) I can avoid importing it along with the other useful instances
>       ii) and the mtl could provide alternative instances.
>     An alternative to breaking out the modules would be to not provide
> the instance.
>     Another, more radical alternative could involve phantom types.
> I don't know of any in the mtl, but this same consideration might be
> applicable to other libraries with "arbitrary" instances.

It was discussed in length, that different instances for the same
class/type pair leads to trouble sooner or later. (keyword "orphan
instances") - Just imagine people who import two instances via two
different import paths, then the compiler does not know, which instances
to use.
 Instead newtype is the answer.

More information about the Libraries mailing list