Kak*_*aji 2 monads haskell monad-transformers
我有以下新类型声明。它包装了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)
Run Code Online (Sandbox Code Playgroud)
我希望此新类型是的实例,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
| ^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
MonadTrans考虑到基础类型ExceptT是的实例,我不明白为什么不能导出MonadTrans。
问题在于,如果此推导有效,则您的实例MonadTrans将转换函子f,而ExceptT您希望用作的基数的实例正在转换monad ReaderT TrxDbFileBasedEnv f。
这些在表示上并不等效,因此GeneralizedNewtypeDeriving无法为您提供帮助。
这是另一种思考方法:尝试手动实现该类。如果尝试这样做,您将看到lift必须像这样定义:
lift = TrxDbFileBased . lift . lift
Run Code Online (Sandbox Code Playgroud)
即,第一升降f成ReaderT,再吊装ReaderT入ExceptT,然后包装全部在TrxDbFileBased。但是GND希望不进行无操作包装,这意味着直接重复使用方法字典,因为类型在表示上是等效的。您的情况并非如此。