hgi*_*sel 8 haskell state-monad
我完全混淆了
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
Run Code Online (Sandbox Code Playgroud)
和
type State s = StateT s Identity
Run Code Online (Sandbox Code Playgroud)
和
class Monad m => MonadState s m | m -> s
Run Code Online (Sandbox Code Playgroud)
dup*_*ode 16
曾几何时,有一种State
类型:
-- Not the current definition.
newtype State s a = State {runState :: s -> (a, s)}
Run Code Online (Sandbox Code Playgroud)
State s a
值本质上是取状态并产生结果和更新状态的函数.通过使元组改组需要隐含地处理输出Functor
,合适的Applicative
和Monad
实例使得以更方便的方式组成这些函数成为可能(a, s)
.借助操纵国家的少数基本操作......
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
Run Code Online (Sandbox Code Playgroud)
...可以避免提及底层s -> (a, s)
类型,并编写感觉有状态的代码.
StateT s
是一个monad变压器图案后State s
:
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
Run Code Online (Sandbox Code Playgroud)
该变换器在基本monad上添加了上述状态处理能力m
.它配备了Functor
,Applicative
和Monad
实例,以及版本get
和put
.
如果m
,基地单子,在StateT s m
IS Identity
中,伪仿...
newtype Identity a = Identity {runIdentity :: a}
Run Code Online (Sandbox Code Playgroud)
...我们得到的东西相当于普通的旧东西State s
.既然如此,变形金刚定义State
为同义词......
type State s = StateT s Identity
Run Code Online (Sandbox Code Playgroud)
......而不是单独的类型.
至于MonadState
它,它迎合了两种不同的需求.首先,我们可以使用monad变压器机器StateT s m
作为变压器堆栈中其他变压器的基础单元(任意示例:) MaybeT (StateT Int IO)
.在这种情况下,虽然,lift
从MonadTrans
必要使用get
和put
.在这种情况下直接使用操作的一种方法是MonadState
:它将它们作为方法提供......
-- Abridged class definition.
class Monad m => MonadState s m | m -> s where
get :: m s
put :: s -> m ()
state :: (s -> (a, s)) -> m a
Run Code Online (Sandbox Code Playgroud)
......这样我们就可以拥有涉及StateT
我们感兴趣的任何变压器组合的实例.
instance Monad m => MonadState s (StateT s m) where -- etc.
instance MonadState s m => MonadState s (MaybeT m) where -- etc.
-- And so forth
Run Code Online (Sandbox Code Playgroud)
其次,如果我们想要一个实现与变换器中的实现不同的状态monad ,我们可以使它成为一个实例MonadState
,这样我们就可以保持相同的基本操作,只要我们写类型签名MonadState
,就有了如果需要,更容易更改实现.
State
用于您的正常状态单子。这是三者中最简单的。(在一些较旧的教程中,您可能会看到使用State
构造函数,但这已被替换为state
函数,因为State s
现在是 的类型别名StateT s Identity
。)
StateT
是 monad 的 monad 转换器State
。它允许您将任意 monad 放入状态,从而增加了一层通用性。这对于简单的解析器很有用,它可以使用例如StateT [Token] Maybe Result
将解析表示为可能失败的有状态操作。
MonadState
将情况概括得更远。有一个实例Monad m => MonadState s (StateT s m)
,但也有一些实例,例如允许您对 的 monad 转换器执行有状态操作的实例StateT
。所有基本状态函数(get
、set
、modify
等)都可以与 的实例一起使用MonadState
。