Haskell 用变换器堆栈从一个新类型派生MonadFree

Haskell 用变换器堆栈从一个新类型派生MonadFree,haskell,free-monad,newtype,deriving,Haskell,Free Monad,Newtype,Deriving,我试图从一个newtype派生出MonadFree,但我就是解不出来。我目前的代码是: 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 =&

我试图从一个
newtype
派生出
MonadFree
,但我就是解不出来。我目前的代码是:

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)
我得到

• 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)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果有人有任何建议,我们将不胜感激。

提供了
wrap
的默认定义:

wrap::(m~tn,MonadTrans,monadfreefn,函子f)=>f(ma)->ma

GHC正在尝试使用此定义,但找不到
MonadTrans
实例

您可以为
ApplicationStack
定义一个
MonadTrans
实例,也可以引导GHC将
ApplicationStack
MonadFree
实例改为基于
StateT
MonadFree
实例。如果您使用的是GHC 8.2或更新版本,最简单的方法是使用。看起来像

派生新类型实例MonadFree f p=>MonadFree f(ApplicationStack srp)


对于较旧的GHC,在正确的模块中激活正确的扩展需要一些技巧。

这不应该是
实例MonadFree f p…
而不是
派生实例…
。这两种方式都是相同的错误。感谢您的帮助。不幸的是,当我尝试派生MonadTrans时,“无法使用新类型策略生成“MonadTrans(ApplicationStack s r)”的派生实例:无法在“ApplicationStack”的新类型声明中充分减少表示类型”我将手动定义
MonadTrans
实例,不要试着去推导。很抱歉,我在回答中不清楚这一点。我无法详细解释GHC新类型派生是如何工作的;我想我已经看到了足够多的错误,可以接受这样的错误,它不适用于像这样洗牌类型参数的新类型。