所以我有这个代码
{-# 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
我让编译器抱怨它无法证明m
的签名中的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
能够通过内部monad 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 ...)
愚蠢我。
答案 0 :(得分:4)
解决方案是从MyStateT
定义中删除约束:
newtype MyStateT a b { runMyStateT :: StateT A a b }
deriving (Functor, Applicative, Monad, MonadIO, MonadState A)
数据类型约束基本上是无用的,因为您无论如何都需要将它们放入函数签名中。因此,该功能实际上是deprecated。
我认为我需要约束才能实例化如下:
不是真的;如果没有它,instance MonadA a => MonadA (MyStateT a)
会正常工作。
f
的这种实现也会起作用吗?
会的。请注意,当您为MonadTrans
提供MyStateT
实例时,实际上并不需要明确地使用MyStateT
包装:
instance MonadA a => MonadA (MyStateT a) where
f = lift . f