在Haskell中,状态单子(State Monad)在哪里,我如何使用它?

4

我正在学习状态单子(State Monad),有人告诉我它已经不再存在了,那么第一个问题是为什么Haskell移除了它?

另外当我在使用时

import Data.Functor.Identity
import Control.Monad.Trans.State

type State s = StateT s Identity

我明白了

Ambiguous occurrence ‘StateIt could refer to
       either ‘Control.Monad.Trans.State.State’
           or ‘Main.State’,

但是当我尝试输入:t State时,却没有找到任何结果。这有点自相矛盾,让我怀疑它是否存在。

最终,我自己动手写了它。

newtype State s a = State { runState :: s -> (a, s) }

但我还需要其他功能,比如putget等,它们在哪里呢?

使用:i get,可以找到MonadState,这是State的新实现吗?


2
是的,State类型构造器不再存在。相反,您可以使用位于MonadState类型类中的state函数。更多信息请查看Control.Monad.State.Lazy - Redu
你说你被告知状态单子“不再存在”。我认为值得指出的是,这并不完全正确。作为独立单子的 State 不再存在了,但 State 单子仍然存在;只不过现在它是通过另一个 StateT 单子来定义,而不是作为自己单独的单子实现。这个新的状态单子位于 Control.Monad.Trans.State 模块中,在 transformers 库中。编辑: 我刚才注意到你已经知道了 Control.Monad.Trans.State —— 对于冗余的评论感到抱歉! - bradrn
1个回答

12

我遇到了“Ambiguous occurrence”错误

好的,让我们尝试你发布的代码。

cat <<EOF >umi.hs
import Data.Functor.Identity
import Control.Monad.Trans.State

type State s = StateT s Identity
EOF
ghci umi.hs

我们需要获取
Ok, one module loaded.

那么其实没问题。我猜你有更多的代码尝试使用 State,但是因为你已经导入了一个 State 并且不需要定义自己的 State 类型,所以它是模糊的。

当我尝试 :t State 时,什么都没有。这是自相矛盾的

当你尝试 :t State 时,你会得到更多的东西,而不只是什么都没有:

:t State

<interactive>:1:1: error:
     Data constructor not in scope: State

请仔细阅读,它说的是“数据构造函数”,而不是“类型”或“类型构造函数”。您无法检查类型(:t:type的缩写)。但是,您可以使用info命令:

> :i State
type Control.Monad.Trans.State.State s =
  StateT s Identity :: * -> *
        -- Defined in ‘Control.Monad.Trans.State.Lazy’

type Main.State s = StateT s Identity :: * -> *
        -- Defined at umi.hs:4:5

因此,您可以看到,您的(Main)类型别名与您从Control.Monad.Trans.State导入的类型别名是多余的。解决方案?只需不定义您的类型别名。
编辑:以上内容旨在澄清一些误解。在此回答您的实际问题。
“状态单子”在哪里?
Haskell库中定义了许多状态单子。最受欢迎的是来自transformers包的Control.Monad.Trans.State。还有一个monadlib版本的State和完全不同的MonadState类(在mtl包中),它是对具有某种状态概念的任何单子进行获取和设置操作的一对。
我该如何使用它?
嗯,您导入模块并可以运行StateMonadicOperation initialState:
> runState (mapM (\x -> state $ \s -> (x,s+x)) [1..4])  9
([1,2,3,4],19)

如果你有具体的问题,可以在stackoverflow上找到很多关于状态单子的问题。

我想知道这个是否存在?

这取决于你问题中的 it。虽然有一个 State 类型构造器,但没有 State 数据构造器。

使用 :i get 命令,我发现 MonadState,这是 State 的新实现吗?

不是。状态单子 State 在变换器中定义为:

type State s = StateT s Data.Functor.Identity.Identity :: * -> *
newtype StateT s (m :: * -> *) a
  = StateT {runStateT :: s -> m (a, s)}

有一个带有数据构造函数和类型别名的transformer和身份monad。

相比之下,MonadState只是获取和设置值能力的抽象:

class Monad m => MonadState s (m :: * -> *) | m -> s where
  get :: m s
  put :: s -> m ()

可能值得明确指出的是,在单子变换器的定义下,runState 不是特定 State 类型中的字段名称,而只是一个定义为 \m -> runIdentity . runStateT m 的函数,以隐藏 StateT 产生的 Identity 值的必要解包。 - chepner
喜欢你的小 mapM runstate 示例! - guthrie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接