了解State Monad的`get`

时间:2017-04-24 12:16:13

标签: haskell

假设:

*Main> let s = state $ \x -> ("foo", x)
*Main> :t s
s :: MonadState s m => m [Char]

我试图调用get s,但得到了以下编译时错误:

*Main> :t get
get :: MonadState s m => m s

*Main> let x = get s

<interactive>:95:5: error:
    • Non type-variable argument
        in the constraint: MonadState t ((->) (m [Char]))
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        x :: forall s (m :: * -> *) t.
             (MonadState s m, MonadState t ((->) (m [Char]))) =>
             t

然后,我添加了扩展名:

*Main> :set -XFlexibleContexts

但是,它仍然没有编译:

*Main> let result = get s

<interactive>:9:5: error:
    • Could not deduce (MonadState s0 m0)
      from the context: (MonadState s m, MonadState t ((->) (m [Char])))
        bound by the inferred type for ‘result’:
                   (MonadState s m, MonadState t ((->) (m [Char]))) => t
        at <interactive>:9:5-18
      The type variables ‘s0’, ‘m0’ are ambiguous
    • In the ambiguity check for the inferred type for ‘result’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      When checking the inferred type
        result :: forall s (m :: * -> *) t.
                  (MonadState s m, MonadState t ((->) (m [Char]))) =>
                  t

请解释为什么它没有编译。

2 个答案:

答案 0 :(得分:5)

仔细看看箭头。 get不接受任何争论:

get :: MonadState s m => m s
--     ^^^^^^^^^^^^^^
--     constraint, not type

s

也不是
s :: MonadState s m => m [Char]
--   ^^^^^^^^^^^^^^
--   constraint, not type

我们可以将这些有状态计算与>>结合起来,因为任何MonadState s m也是Monad

setAndGet = s >> get

我们可以查看setAndGetrunState的结果:

ghci> runState setAndGet "example"
("example","example")

答案 1 :(得分:0)

状态monad中的状态类似于underground river,它遵循计算的表面路径。它隐藏了你不需要它的状态,让你专注于组成构成计算的(monadic)函数。

get就像一条井,可以轻松进入那条河流,让你在需要时将状态带到空旷的地方。这是你所遵循的道路的一部分&#34;可以这么说,不是你应用于monadic动作的一些外部功能。