Deriving MonadFree from a newtype with a transformer stack

126 Views Asked by At

I’m trying to derive MonadFree from a newtype and I just can’t work it out. My current code is:

newtype ApplicationStack s r p m =
  ApplicationStack { runApplication :: StateT s (ReaderT r p) m }
  deriving (Functor, Applicative, Monad, MonadState s, MonadReader r)

deriving instance MonadFree f p => MonadFree f (ApplicationStack s r p)

and I get

• Could not deduce (transformers-0.5.5.0:Control.Monad.Trans.Class.MonadTrans
                      (ApplicationStack s r))
    arising from a use of ‘Control.Monad.Free.Class.$dmwrap’
  from the context: MonadFree f p
    bound by the instance declaration
    at src/Application/Commands/Base.hs:41:10-62
• In the expression:
    Control.Monad.Free.Class.$dmwrap @(f) @(ApplicationStack s r p)
  In an equation for ‘Control.Monad.Free.Class.wrap’:
      Control.Monad.Free.Class.wrap
        = Control.Monad.Free.Class.$dmwrap @(f) @(ApplicationStack s r p)
  In the instance declaration for
    ‘MonadFree f (ApplicationStack s r p)’
   |
41 | instance MonadFree f p => MonadFree f (ApplicationStack s r p)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If anyone has any suggestions that would be really appreciated.

1

There are 1 best solutions below

2
On

The definition of MonadFree provides a default definition of wrap:

wrap :: (m ~ t n, MonadTrans t, MonadFree f n, Functor f) => f (m a) -> m a

GHC is trying to use this definition, but cannot find a MonadTrans instance.

You can define a MonadTrans instance for ApplicationStack, or you can guide GHC to base the MonadFree instance for ApplicationStack on the MonadFree instance for StateT, instead. If you're using GHC 8.2 or newer, the easiest way to do the later is with deriving strategies. It looks something like

deriving newtype instance MonadFree f p => MonadFree f (ApplicationStack s r p)

With older GHC, it takes some fiddling to get the right extensions active in the right modules.