newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
type State s = StateT s Identity
class Monad m => MonadState s m | m -> s
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
type State s = StateT s Identity
class Monad m => MonadState s m | m -> s
从前,有一个State
类型:
-- Not the current definition.
newtype State s a = State {runState :: s -> (a, s)}
State s a
值是,在本质上,采取的状态,并产生一个结果,并更新状态的功能。合适的Functor
,Applicative
和Monad
实例使得有可能通过使得元组混排需要处理输出隐式来更方便地组合这些函数。与操作状态操作的几个基本的帮助...
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
...它是可能避免的潜在s -> (a, s)
类型的任何提及,并编写代码感觉状态。
StateT s
是单子变压器State s
之后图案化:
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
这种变压器的顶上添加碱单子,m
上述状态的处理能力。它附带Functor
,Applicative
和Monad
实例,以及get
和put
的版本。
如果m
,基地单子,在StateT s m
是Identity
,伪仿...
newtype Identity a = Identity {runIdentity :: a}
...我们得到的东西等同于普通的旧State s
。如此,变压器将State
定义为同义词...
type State s = StateT s Identity
...而不是作为一个单独的类型。
至于MonadState
,它迎合了两种不同的需求。首先,我们可以使用monad变压器机器将StateT s m
作为变压器堆栈中某个其他变压器的基本monad(任意示例:MaybeT (StateT Int IO)
)。在这种情况下,使用get
和put
时,需要lift
从MonadTrans
。直接在这样的情况下使用该业务的一种方式是通过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
...这样我们就可以对涉及StateT
变压器的任意组合,我们有兴趣的情况下, 。
instance Monad m => MonadState s (StateT s m) where -- etc.
instance MonadState s m => MonadState s (MaybeT m) where -- etc.
-- And so forth
其次,如果我们希望有一个比变压器不同的实现的状态单子,我们可以把它的MonadState
一个实例,让我们保持相同的基本操作,并为只要我们写类型签名根据MonadState
计算,如果需要,可以更容易地更改实现。
State
是你的正常状态单子。这是三者中最简单的。 (在一些老的教程,你可以看到使用State
构造,但这已经被替换为state
功能,因为State s
现在是StateT s Identity
一个类型别名。)
StateT
是为State
单子的单子转换。它增加了一层通用性,允许你在状态中放置一个任意monad。这对简单的解析器很有用,它可以使用例如StateT [Token] Maybe Result
将解析表示为可能失败的有状态操作。
MonadState
将情况概括得更远。有一个实例Monad m => MonadState s (StateT s m)
,但也有一些实例,如允许您在单粒变换器StateT
上执行有状态操作的实例。所有基本状态功能(get
,set
,modify
等)可与MonadState
的实例一起使用。
你确切的问题是什么?你想要完成什么类型的目标?你的困惑来自哪里?你不知道'newtype','type'和'class'是什么?如果你只是不理解这些结构,那么只需阅读一些Haskell教程。 StackOverflow是针对特定问题的。 – Shersh
问题是...? :) – Alec