gpt4 book ai didi

haskell - 无法为 newtype 创建 MonadTrans 的派生实例

转载 作者:行者123 更新时间:2023-12-02 16:44:00 29 4
gpt4 key购买 nike

我有以下新类型声明。它包装了一个 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 必须定义如下:

lift = TrxDbFileBased . lift . lift

也就是说,首先将 f 提升为 ReaderT,然后将 ReaderT 提升为 ExceptT,然后包装所有TrxDbFileBased 中的内容。但 GND 期望除了无操作包装之外什么也不做,这意味着直接重用方法字典,因为类型在表示上是等效的。您的情况并非如此。

关于haskell - 无法为 newtype 创建 MonadTrans 的派生实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57650284/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com