Haskell TeletypeIO的StateMonad实例
所以,我有这个数据类型(它来自这里:): 我想为它写一个国家实例。我已经为它编写了Monad和应用程序实例Haskell TeletypeIO的StateMonad实例,haskell,io,monads,semantics,state-monad,Haskell,Io,Monads,Semantics,State Monad,所以,我有这个数据类型(它来自这里:): 我想为它写一个国家实例。我已经为它编写了Monad和应用程序实例 instance MonadState (IO s) where get = GetChar (\c -> Done c) put = PutChar c (Done ()) state f = Done (f s) 我不认为我完全理解在这里应该执行什么状态(以前称为“修改”) state :: (s -> (a, s)) -> m a 我还搞
instance MonadState (IO s) where
get = GetChar (\c -> Done c)
put = PutChar c (Done ())
state f = Done (f s)
我不认为我完全理解在这里应该执行什么状态(以前称为“修改”)
state :: (s -> (a, s)) -> m a
我还搞砸了申报。我真的不明白出了什么问题,更不用说如何解决了。谢谢你的帮助
Expecting one more argument to ‘MonadState (IO s)’
Expected a constraint,
but ‘MonadState (IO s)’ has kind ‘(* -> *) -> Constraint’
In the instance declaration for ‘MonadState (IO s)’
MonadState
接受两个参数,顺序如下:
IO
:
instance MonadState _ IO where
...
您需要弄清楚是什么代替了下划线,正如我在注释中提到的,您的类型实际上不包含任何状态,因此对它来说,
StateMonad
实例是毫无意义的
然而,由于这只是一个练习(也基于注释),我想从技术上实现该实例是可以的,即使它没有达到您期望的效果
首先,您遇到的编译器错误告诉您,MonadState
类实际上包含两个参数——状态类型和monad类型,其中monad必须具有kind*->*
,也就是说,具有一个类型参数,比如可能
,或者list,或者标识
在您的例子中,所讨论的monad(不是真正的monad,但ok)是IO
,而您的“状态”类型是Char
,因为这就是您的get
ting和put
ting。因此,声明必须如下所示:
instance MonadState Char IO where
其次,state方法没有您声称的签名(s->s)->ms
,而是(s->(a,s))->ma
。看见它应该做的是在monadm
中创建一个计算,该计算来自一个函数,该函数获取一个状态并返回“result”加上新的(更新的)状态
还要注意的是,这是状态monad上最通用的操作,get
和put
都可以用State
表示:
get = state $ \s -> (s, s)
put s = state $ \_ -> ((), s)
这意味着您不必自己实现get
和put
。您只需要实现state
函数,而get
/put
将来自默认实现
顺便说一句,这也是另一种方式:如果定义get
和put
,则状态的定义将来自默认值:
state f = do
s <- get
let (a, s') = f s
put s'
return a
作为进一步的练习,我鼓励您看看get
和put
将如何展开,从我上面给出的定义开始,逐步进行替换。在这里,我将为您介绍几个第一步:
get = state $ \s -> (s, s)
-- Substituting definition of `state`
= GetChar $ \c -> let (a, c') = (\s -> (s, s)) c in PutChar c' (Done a)
-- Substituting (\s -> (s, s)) c == (c, c)
= GetChar $ \c -> let (a, c') = (c, c) in PutChar c' (Done a)
= <and so on...>
get=state$\s->(s,s)
--替换`国家'的定义`
=GetChar$\c->let(a,c')=(\s->(s,s))c在PutChar c'(完成a)中
--替换(\s->(s,s))c==(c,c)
=GetChar$\c->let(a,c')=(c,c)在PutChar c'(完成a)中
=
您的类型不包含任何类型的状态,因此对于它来说,MonadState
实例是毫无意义的。您试图解决的问题是什么?@FyodorSoikin任务是:“为Teletype/IO定义MonadState实例”。之后还有一个问题“这个实例的行为与通常的状态类型有何不同?”,可能就是这样。哦,这是家庭作业吗?@FyodorSoikin不是真的,我只是在学习Haskell,这是我发现的任务之一。这有关系吗?我理解为什么get
和put
是这样的(使用state
),我只是不理解为什么Haskell已经知道state
应该如何工作,没有定义。Haskell不知道。这是在库中定义的<代码>获取
/放置
通过状态
定义,状态
通过获取
/放置
定义。无论您选择实现哪一部分,另一部分都将免费提供。
state f = GetChar $ \c -> let (a, c') = f c in PutChar c' (Done a)
get = state $ \s -> (s, s)
-- Substituting definition of `state`
= GetChar $ \c -> let (a, c') = (\s -> (s, s)) c in PutChar c' (Done a)
-- Substituting (\s -> (s, s)) c == (c, c)
= GetChar $ \c -> let (a, c') = (c, c) in PutChar c' (Done a)
= <and so on...>