【问题标题】:Confusion about StateT, State and MonadState关于 StateT、State 和 MonadState 的混淆
【发布时间】:2017-09-12 07:51:10
【问题描述】:

我很困惑

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

【问题讨论】:

  • 您的具体问题是什么?你想要实现什么类型的目标?你的困惑从何而来?你不知道newtypetypeclass是什么?如果您只是不了解这些结构,那么只需阅读一些 Haskell 教程。 StackOverflow 是针对特定问题的。
  • 问题是……? :)

标签: haskell state-monad


【解决方案1】:

State 用于您的正常状态单子。这是三个中最简单的。 (在一些较早的教程中,您可能会看到使用 State 构造函数,但这已被 state 函数替换,因为 State s 现在是 StateT s Identity 的类型别名。)

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

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

【讨论】:

    【解决方案2】:

    从前,有一个State类型:

    -- Not the current definition.
    newtype State s a = State {runState :: s -> (a, s)}
    

    State s a 值本质上是获取状态并产生结果和更新状态的函数。合适的FunctorApplicativeMonad 实例可以通过使元组改组需要隐式处理(a, s) 输出来以更方便的方式组合这些函数。在少数操纵状态的基本操作的帮助下......

    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)}
    

    此转换器在基本 monad m 之上添加了上述状态处理功能。它带有FunctorApplicativeMonad 实例,以及getput 的版本。

    如果m,基本单子,在StateT s mIdentity,虚拟函子...

    newtype Identity a = Identity {runIdentity :: a}
    

    ...我们得到的东西等同于普通的旧State s。既然如此,transformersState 定义为同义词...

    type State s = StateT s Identity
    

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

    至于MonadState,它满足了两种不同的需求。首先,我们可以使用 monad 变压器机制将 StateT s m 作为变压器堆栈中其他变压器的基本 monad(任意示例:MaybeT (StateT Int IO))。但是,在这种情况下,lift 来自 MonadTrans 成为使用 getput 所必需的。在这种情况下直接使用操作的一种方法是通过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
    

    其次,如果我们想要一个状态 monad 的实现不同于 transformers 中的实现,我们可以将其设为 MonadState 的实例,这样我们就可以保持相同的基本操作和,只要我们按照MonadState 编写类型签名,如果需要,更改实现就更容易了。

    【讨论】:

      猜你喜欢
      • 2011-05-07
      • 2020-05-25
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 2016-04-24
      • 1970-01-01
      • 2014-07-29
      相关资源
      最近更新 更多