假设:
*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
请解释为什么它没有编译。
答案 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
我们可以查看setAndGet
与runState
的结果:
ghci> runState setAndGet "example"
("example","example")
答案 1 :(得分:0)
状态monad中的状态类似于underground river,它遵循计算的表面路径。它隐藏了你不需要它的状态,让你专注于组成构成计算的(monadic)函数。
get
就像一条井,可以轻松进入那条河流,让你在需要时将状态带到空旷的地方。这是你所遵循的道路的一部分&#34;可以这么说,不是你应用于monadic动作的一些外部功能。