鉴于:
*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)
请解释为什么它没有编译.
仔细看看箭头.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)
我们可以看看结果setAndGet有runState:
ghci> runState setAndGet "example"
("example","example")
Run Code Online (Sandbox Code Playgroud)