我有以下新类型声明。它包装了Monad堆叠变压器,堆叠了一些标准的mtl monad,例如Reader和Except。newtype TrxDbFileBased f a = TrxDbFileBased { unTrxDbFileBased :: ExceptT TrxDbError (ReaderT TrxDbFileBasedEnv f) a } deriving ( Functor , Applicative , Monad , MonadError TrxDbError , MonadReader TrxDbFileBasedEnv , MonadIO , MonadTrans )data TrxDbFileBasedEnv = TrxDbFileBasedEnv { workingDirectory :: FilePath } deriving (Show)data TrxDbError = TrxDbErrorIO TrxDbFileBasedEnv IOException | TrxDbErrorStr TrxDbFileBasedEnv String deriving (Show)我希望此新类型是MonadTrans的实例,但出现以下错误。 • Can't make a derived instance of ‘MonadTrans TrxDbFileBased’ (even with cunning GeneralizedNewtypeDeriving): cannot eta-reduce the representation type enough • In the newtype declaration for ‘TrxDbFileBased’ |31 | , MonadTrans | ^^^^^^^^^^考虑到基础类型是MonadTrans(它是ExceptT的一个实例),我不明白为什么不能导出MonadTrans。 最佳答案 问题在于,如果此推导有效,则您的MonadTrans实例将转换函子f,而您希望将ExceptT的实例用作推导基数,则将转换monad 。这些在表示上并不等效,因此ReaderT TrxDbFileBasedEnv f在这里无法为您提供帮助。这是另一种思考方法:尝试手动实现该类。如果尝试这样做,您将看到必须像这样定义GeneralizedNewtypeDeriving:lift = TrxDbFileBased . lift . lift也就是说,首先将lift放入f,然后将ReaderT放入ReaderT,然后将所有内容包装在ExceptT中。但是GND希望只做无操作包装,这意味着直接重复使用方法字典,因为类型在表示上是等效的。您的情况并非如此。
10-06 04:06