Monday, 19 August 2013

Haskeline: Implementing `MonadException` instance for `ReaderT r (StateT s m)` stack

Haskeline: Implementing `MonadException` instance for `ReaderT r (StateT s
m)` stack

Let's say I have the following monad transformer stack (r and s left as ()
for simplicity),
newtype MyMonad m a = MM (ReaderT () (StateT () m a)
If I want to use this as a base monad for haskeline's InputT, I need a
System.Console.Haskeline.MonadException instance. Given the apparent
complexity of these instances, I'd prefer to let the compiler derive this
for me with GeneralizedNewtypeDeriving. Specifically, I would expect the
following to typecheck,
{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving,
FlexibleContexts #-}
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.IO.Class
import Control.Applicative
import System.Console.Haskeline.MonadException
newtype MyMonad m a = MM (ReaderT () (StateT () m) a)
deriving (Functor, Applicative, Monad, MonadIO)
deriving instance (MonadException m) => MonadException (MyMonad m)
Yet sadly, this gives me,
/home/bgamari/hi.hs:11:1:
Could not deduce (MonadException (StateT () m))
arising from the superclasses of an instance declaration
from the context (MonadIO (MyMonad m), MonadException m)
bound by the instance declaration at /home/bgamari/hi.hs:11:1-66
Possible fix:
add an instance declaration for (MonadException (StateT () m))
In the instance declaration for `MonadException (MyMonad m)'
Looking at the provided instances for StateT and ReaderT,
instance MonadException m => MonadException (ReaderT r m)
instance MonadException m => MonadException (StateT s m)
it seems perfectly reasonable to expect the compiler to deduce the StateT
instance. Am I expecting too much of cunning GeneralizedNewtypeDeriving?
How is one to implement this instance short of open-coding it?

No comments:

Post a Comment