0

所以我有这个代码

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import MonadA

data A = A

newtype MonadA a => MyStateT a b { runMyStateT :: StateT A a b }
    deriving (Functor, Applicative, Monad, MonadIO, MonadState A)

instance MonadTrans MyStateT where
    lift = MyStateT . lift

我让编译器抱怨它无法证明mfrom 签名lift是类型的,MonadA或者这就是我阅读这些神秘错误消息的方式。

Could not deduce (MonadA m) arising from a use of `MyStateT'
from the context (Monad m)
  bound by the type signature for
             lift :: Monad m => m a -> MyStateT m a

有没有办法解决这个问题?我认为我需要约束才能实例化如下:

instance MonadA a => MonadA (MyStateT a) where
    f = MyStateT . lift . f

还会有这样的执行f工作吗?(由于上述错误,我没有走那么远)。我希望f在右侧解决f内部单子a


编辑:它确实有助于删除类型约束newtype MonadA a => MyStateT ...以避免我提到的确切错误。但是,我之前将另一个错误归因于同一件事,请考虑上面示例代码的延续(重复某些部分,现在没有类型限制):

class MonadB m where
    fB :: m ()

newtype MyStateT m a = MyStateT { runMyStateT :: StateT A m a}
    deriving (... MonadState A ...)

instance MonadTrans MyStateT where
    lift = MyStateT . lift

instance MonadA a => MonadA (MyStateT a) where
    f = lift . f

instance MonadA a => MonadB (MyStateT a) where
    fB = lift (modify (...))

错误是

Could not deduce (a ~ StateT A m0) from context (MonadA (MyStateT a), MonadA a)

在实施中fB。早些时候我试过class MonadA m => MonadB m没有用。a与匹配甚至没有意义StateT A m。因为MyStateT它的一个实例MonadState A应该可以工作,不是吗?

编辑

好的,让它工作:

fB = MyStateT (modify ...)

愚蠢的我。

4

1 回答 1

4

解决方案是从MyStateT定义中删除约束:

newtype MyStateT a b { runMyStateT :: StateT A a b }
    deriving (Functor, Applicative, Monad, MonadIO, MonadState A)

数据类型约束本质上是无用的,因为无论如何您都需要将它们放在函数签名中。因此,该功能实际上已弃用

我认为我需要约束才能实例化如下:

并不真地; instance MonadA a => MonadA (MyStateT a)没有它就可以正常工作。

还会有这样的执行f工作吗?

它会。请注意,当您为 提供了一个MonadTrans实例时MyStateT,您实际上不需要MyStateT显式包装:

instance MonadA a => MonadA (MyStateT a) where
    f = lift . f
于 2015-09-15T09:57:07.910 回答