Haskell 理解国家元
我是一个haskell初学者,试图理解StateMonad的这个定义,特别是bind操作。它摘自第4页Haskell 理解国家元,haskell,monads,state-monad,Haskell,Monads,State Monad,我是一个haskell初学者,试图理解StateMonad的这个定义,特别是bind操作。它摘自第4页 首先,您需要了解>>=的类型;我想你会的,因为它在那篇论文的第二页,你已经通过了 如果我们定义runState,bind的定义可能更容易理解 newtype SM s a = SM (s -> (a, s)) runState :: SM a -> s -> (a, s) runState (SM f) s = f s -- this is equival
首先,您需要了解
>>=
的类型;我想你会的,因为它在那篇论文的第二页,你已经通过了
如果我们定义runState
,bind的定义可能更容易理解
newtype SM s a = SM (s -> (a, s))
runState :: SM a -> s -> (a, s)
runState (SM f) s = f s
-- this is equivalent to
-- runState (SM f) = f
runState
通过提取转换状态的函数f
并将其应用于初始状态s
来运行状态monad。函数f
返回类型为(a,s)
的元组。元组包含依赖于状态的值(类型a
)和新状态(类型s
)。以下是等效的
let (a, s') = runState x s
in ...
let SM x' = x
(a, s') = x' s
in ...
这两个函数都提取函数x'
,了解状态如何从x
转换,然后将其应用于初始状态s
。结果元组(a,s')
包含依赖于状态的值a
,以及新状态s'
我们可以用runState
替换>=
定义中的SM
模式匹配
x >>= f = SM (\s -> let
(a, s') = runState x s
(b, s'') = runState (f a) s'
in (b, s''))
现在我们要一件一件地看一遍
Bind构造一个新的StateMonad
,该函数依赖于一些初始状态s
。它返回一个状态相关值b
和一个新状态s'
:
通过使用初始状态s
运行状态monadx
计算状态相关值a
和新状态s'
:
x >>= f = SM (\s -> let
...
in (b, s''))
let
(a, s') = runState x s
根据用户提供的函数f
和依赖于状态的值A
确定新的状态monadf A
。第二个状态monad使用中间状态s'
运行。它计算另一个状态相关值b
和最终状态s'
第二个依赖于状态的值
b
和最终状态s'
是为新的StateMonad
构造的函数返回的,这是对Cirdec
的一个略短的补充答案
首先,回想一下在x>=f
中,x
是状态单子,f
是返回状态单子的fn,x>=f
也是状态单子
基本思路如下。给定一些当前状态s
(稍后当我们运行由x>=f
表示的状态monad时将提供),我们首先希望使用s
运行x
,这将产生一些值a
,以及一个新状态s'
。然后我们想运行fa,这给了我们另一个状态monad。但是,我们不只是想在任何状态下运行这个结果状态monadfa
;相反,我们希望用x
产生的状态运行它,即s'
,给我们一些新值b
和一些新状态s'
x>>=f
将表示从s->(b,s')
进行的计算
请记住:使用状态单子的全部目的是避免将状态作为另一个参数显式传递给所有函数(这将非常混乱,非常快)。因此,这里的想法是,每当我们将动作绑定到状态monad时,都要在后台正确地执行状态线程
为此,我们(1)在
x
上进行模式匹配以获取内部fn,然后(2)使用当前状态s
运行此函数以获得结果a
和一些新状态s'
。然后我们(3)计算fa,它返回一个状态monad,并在这个monad上进行模式匹配以得到内部的fn;然后(4)使用状态s'
运行fn,以获得值b
和一些最终状态s'
。(1) 到(4)对应于紧跟在后面的四行,让插入代码。你知道什么,我们刚刚定义了一个fn,从s
到(b,s“”)
,它在幕后正确地传递状态。现在我们将把它包装在一个构造函数中,我们就完成了x>>=f
现在表示我们可以稍后通过提供初始状态来运行的计算 你的抄本缺少一个非常重要的部分。let
的第二行应该是SM(a,s')=x's
。
let
(a, s') = runState x s
(b, s'') = runState (f a) s'