我正在尝试为Monad
提供MonadState
和State'
实例,以计算(>>=), return, get
和put
操作的数量。
data Counts = Counts { binds :: Int
, returns :: Int
, gets :: Int
, puts :: Int
}
newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }
这就是我已经做过的,据我了解发生了什么,这段代码应该可以工作:
instance Monad State' where
return = State' ( \(s, counts) -> (x, s, counts mappend oneReturn))
(>>=) st f = State' ( \(s, counts) -> let (x, s', counts') = runState' (s, counts) in runState' ((f x), (s', counts' mappend oneBind)) )
instance Monad m => MonadState m State' where
get = State' ( \(s, counts) -> (s, s, counts mappend oneGet) )
put st = State' ( \(s, counts) -> ((), st, counts mappend onePut) )
但是我收到此错误消息:
期待
‘State'’
的另一个论点
预期种类为‘* -> *’
,但是‘State'’
的种类为‘* -> * -> *’
为什么?
答案 0 :(得分:4)
要点在句子中
Expected kind ‘* -> *’, but ‘State'’ has kind ‘* -> * -> *’
如果您使用State'
命令通过GHCi检查:k
的类型,您将看到State'
的类型为* -> * -> *
,这简单地说就是需要对其进行参数设置两种类型的*
类型产生最终的*
类型。如您所见,Monad
仅限于* -> *
。例如Maybe
是Monad
,而Maybe Int
不是。
要解决此问题,您需要将状态类型应用于State'
,然后才能将其声明为Monad:
instance Monad (State' s) where
第二部分中的错误有点概念化–声明中的m
是什么? MonadState
是Monad
的子类,因此MonadState
的每个实例也是Monad
的实例。考虑到这一点,正确的符号应该有意义:
instance MonadState s (State' s) where
您不想提及此Monad
-它是从类声明派生的。