首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于StateT、State和MonadState的混淆

关于StateT、State和MonadState的混淆
EN

Stack Overflow用户
提问于 2017-04-16 15:34:31
回答 2查看 6.5K关注 0票数 15

我完全搞不懂

代码语言:javascript
复制
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}

代码语言:javascript
复制
type State s = StateT s Identity

代码语言:javascript
复制
class Monad m => MonadState s m | m -> s
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-16 19:35:39

很久以前,有一种State类型:

代码语言:javascript
复制
-- Not the current definition.
newtype State s a = State {runState :: s -> (a, s)}

State s a值本质上是接受状态并生成结果和更新状态的函数。适当的FunctorApplicativeMonad实例使以更方便的方式组合这些函数成为可能,因为元组改组需要隐式处理(a, s)输出。在一些操纵国家的基本行动的帮助下.

代码语言:javascript
复制
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)

..。可以避免提及底层s -> (a, s)类型,并编写感觉有状态的代码。

StateT s是一种以State s为模式的单片变压器

代码语言:javascript
复制
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}

这个转换器增加了上面描述的状态处理能力,位于一个基本的单模,m之上。它附带了FunctorApplicativeMonad实例,以及getput的版本。

如果m,基单,在StateT s m中是Identity,虚拟函子.

代码语言:javascript
复制
newtype Identity a = Identity {runIdentity :: a}

..。我们得到了类似于普通的旧State s的东西。既然如此,变压器将State定义为同义词.

代码语言:javascript
复制
type State s = StateT s Identity

..。而不是作为一个单独的类型。

至于MonadState,它满足了两种不同的需求。首先,我们可以使用单台变压器机器,在一堆变压器中使用StateT s m作为其它变压器的基座单模(任意例子:MaybeT (StateT Int IO))。但是,在这种情况下,使用liftput就必须使用来自MonadTransget。在这种情况下直接使用操作的一种方法是通过MonadState:它将它们作为方法提供.

代码语言:javascript
复制
-- 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的任何变压器组合的实例。

代码语言:javascript
复制
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编写类型签名,就可以在需要时更容易地更改实现。

票数 35
EN

Stack Overflow用户

发布于 2017-04-16 18:14:06

State是你正常状态下的单曲。这是三者中最简单的。(在一些较早的教程中,您可能会看到State构造函数的使用,但这已经被state函数所取代,因为State s现在是StateT s Identity的类型别名。)

StateTState monad的单一变压器。它通过允许您在状态中放置任意的单块来增加一层通用性。这对于简单的解析器很有用,它可以使用例如StateT [Token] Maybe Result将解析表示为可能失败的有状态操作。

MonadState进一步概括了这种情况。有一个实例Monad m => MonadState s (StateT s m),但也有一些实例,比如允许您对StateT的单台变压器执行有状态操作的实例。所有基本状态函数(getsetmodify等)可以与MonadState实例一起使用。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43438875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档