1

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.

tomphp
  • 307
  • 1
  • 4
  • 10

1 Answers1

0

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.

bergey
  • 3,041
  • 11
  • 17
  • Thanks for your help. Sadly I get the following when trying to derive MonadTrans "Can't make a derived instance of ‘MonadTrans (ApplicationStack s r)’ with the newtype strategy: cannot eta-reduce the representation type enough In the newtype declaration for ‘ApplicationStack’" – tomphp Oct 07 '18 at 16:17
  • I would define the `MonadTrans` instance manually, not try to derive that. Sorry that I wasn't clear about that in my answer. I can't explain how GHC newtype deriving works in detail; I think I've just seen errors like that enough to accept that it won't work for newtypes that shuffle type parameters like this. – bergey Oct 08 '18 at 19:10