了解State Monad的`get`

Kev*_*ith 0 haskell

鉴于:

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

我试着打电话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
Run Code Online (Sandbox Code Playgroud)

然后,我添加了扩展名:

*Main> :set -XFlexibleContexts
Run Code Online (Sandbox Code Playgroud)

但是,它仍然无法编译:

*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
Run Code Online (Sandbox Code Playgroud)

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

Zet*_*eta 5

仔细看看箭头.get没有任何争论:

get :: MonadState s m => m s
--     ^^^^^^^^^^^^^^
--     constraint, not type
Run Code Online (Sandbox Code Playgroud)

也不是s:

s :: MonadState s m => m [Char]
--   ^^^^^^^^^^^^^^
--   constraint, not type
Run Code Online (Sandbox Code Playgroud)

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

setAndGet = s >> get
Run Code Online (Sandbox Code Playgroud)

我们可以看看结果setAndGetrunState:

ghci> runState setAndGet "example"
("example","example")
Run Code Online (Sandbox Code Playgroud)