无法为新类型创建 MonadTrans 的派生实例
Can't make a derived instance of MonadTrans for newtype
我有以下新类型声明。它正在包装一个 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
在这里帮不了你。
这是另一种思考方式:尝试手动实施 class。如果你尝试这样做,你会发现你的 lift
必须这样定义:
lift = TrxDbFileBased . lift . lift
也就是说,首先将 f
提升为 ReaderT
,然后将 ReaderT
提升为 ExceptT
,然后将所有这些包裹在 TrxDbFileBased
中。但是 GND 期望只做无操作包装,这意味着直接重用方法字典,因为类型在表示上是等价的。你的情况不是这样。
我有以下新类型声明。它正在包装一个 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
在这里帮不了你。
这是另一种思考方式:尝试手动实施 class。如果你尝试这样做,你会发现你的 lift
必须这样定义:
lift = TrxDbFileBased . lift . lift
也就是说,首先将 f
提升为 ReaderT
,然后将 ReaderT
提升为 ExceptT
,然后将所有这些包裹在 TrxDbFileBased
中。但是 GND 期望只做无操作包装,这意味着直接重用方法字典,因为类型在表示上是等价的。你的情况不是这样。