[英]State's `put` and `get` functions
I'n looking at the State Monad 's put
and get
: I'n看国家单子的put
和get
:
ghci> :t get
get :: MonadState s m => m s
ghci> :t runState
runState :: State s a -> s -> (a, s)
ghci> runState get [1,2,3]
([1,2,3],[1,2,3])
In get
's type signature: MonadState sm => ms
, how does [1,2,3]
have a type of MonadState sm
? 在get
的类型签名中: MonadState sm => ms
, [1,2,3]
如何具有MonadState sm
类型? It's not clear to me what the types of s
and m
are. 我不清楚s
和m
的类型是什么。
Also, can you please say more as to how to use put
? 另外,您能否详细说明如何使用put
?
ghci> :t put put :: MonadState sm => s -> m () ghci>:t put put :: MonadState sm => s - > m()
Overall, it seems that I don't understand what MonadState sm
is. 总的来说,似乎我不明白MonadState sm
是什么。 Could you please explain with put
and get
examples? 能否请您解释一下同put
和get
的例子吗?
MonadState sm
is a typeclass constraint, not a type. MonadState sm
是类型类约束,而不是类型。 The signature: 签名:
get :: MonadState s m => m s
Says that for some monad m
storing some state of type s
, get
is an action in m
that returns a value of type s
. 说对于某些monad m
存储某种类型s
状态, get
是m
中的一个动作,它返回一个s
类型s
值。 This is pretty abstract, so let's make it more concrete with the less-overloaded version of State
from transformers
: 这是非常抽象的,所以让我们从transformers
使用较少重载的State
版本来使其更具体:
get :: State s s
put :: s -> State s ()
Now say we want to use State
to keep a simple counter. 现在说我们想用State
来保持一个简单的计数器。 Let's use execState
instead of runState
so we can just pay attention to the final value of the state. 让我们使用execState
而不是runState
这样我们就可以关注状态的最终值。 We can get
the value of the counter: 我们可以get
柜台的价值:
> execState get 0
0
We can set the value of the counter using put
: 我们可以使用put
设置计数器的值:
> execState (put 1) 0
1
We can set the state multiple times: 我们可以多次设置状态:
> execState (do put 1; put 2) 0
2
And we can modify the state based on its current value: 我们可以根据其当前值修改状态:
> execState (do x <- get; put (x + 1)) 0
1
This combination of get
and put
is common enough to have its own name, modify
: get
和put
这种组合很常见,有自己的名字, modify
:
> execState (do modify (+ 1)) 0
1
> execState (do modify (+ 2); modify (* 5)) 0
10
MonadState
is the class of types that are monads with state. MonadState
是具有state的monad类型。 State
is an instance of that class: State
是该类的一个实例:
instance MonadState s (State s) where
get = Control.Monad.Trans.State.get
put = Control.Monad.Trans.State.put
So are StateT
(the state monad transformer, which adds state to another monad) and various others. StateT
(状态monad变换器,它将状态添加到另一个monad)和其他各种StateT
也是如此。 This overloading was introduced so that if you're using a stack of monad transformers, you don't need to explicitly lift
operations between different transformers. 引入了这种重载,这样如果你使用一堆monad变换器,你就不需要明确地lift
不同变换器之间的操作。 If you're not doing that, you can use the simpler operations from transformers
. 如果你不这样做,你可以使用transformers
更简单的操作。
Here's another example of how to use State
to encapsulate a map of variables with Data.Map
: 这是另一个如何使用State
来封装Data.Map
变量映射的Data.Map
:
import Control.Monad.Trans.State
import qualified Data.Map as M
action = do
modify (M.insert "x" 2) -- x = 2
modify (M.insert "y" 3) -- y = 3
x <- gets (M.! "x")
y <- gets (M.! "y")
modify (M.insert "z" (x + y)) -- z = x + y
modify (M.adjust (+ 2) "z") -- z += 2
gets (M.! "z") -- return z
main = do
let (result, vars) = execState action M.empty
putStr "Result: "
print result
putStr "Vars: "
print vars
In get's type signature: MonadState sm => ms, how does [1,2,3] have a type of MonadState sm? 在get的类型签名中:MonadState sm => ms,[1,2,3]如何具有MonadState sm类型? It's not clear to me what the types of s and m are. 我不清楚s和m的类型是什么。
ghci> runState get [1,2,3]
The function runState
takes two arguments: the first is the State
action to run, and the second is the initial state. 函数runState
有两个参数:第一个是要运行的State
操作,第二个是初始状态。 So, since the initial state is [1,2,3]
which is a list of integers (*), the state type s
is just [Integer]
. 因此,由于初始状态是[1,2,3]
,它是整数列表(*),因此状态类型s
只是[Integer]
。
(*) Actually, [1,2,3] :: Num a => [a]
before GHCi defaults it, but for simplicity's sake let's use [Integer]
as GHCi does. (*)实际上,在GHCi默认之前, [1,2,3] :: Num a => [a]
,但为了简单起见,我们使用[Integer]
作为GHCi。
Hence, we see that runState
is specialized to 因此,我们看到runState
专门用于
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
Now, about the first argument: 现在,关于第一个论点:
get :: MonadState s m => m s
We must have ms = State sa
because we are passing it to runState
which requires such type. 我们必须有ms = State sa
因为我们将它传递给需要这种类型的runState
。 Hence: 因此:
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState s m => m s
with m s = State [Integer] a
The latter equation can be simplified as follows: 后一个等式可以简化如下:
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState s m => m s
with m = State [Integer]
and s = a
Substituting s
: 代替s
:
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a m => m a
with m = State [Integer]
Substituting m
: 代替m
:
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
Now, the constraint MonadState a (State [Integer])
is satisfied only when a = [Integer]
. 现在,仅当a = [Integer]
时才满足约束MonadState a (State [Integer])
。 This is tricky to see, since the MonasState
type class exploits a functional dependency to enforce that every monad in that class has only one related state type. 这很难看,因为MonasState
类型类利用函数依赖来强制该类中的每个monad只有一个相关的状态类型。 This is also made more complex from State
being a wrapper around StateT
. 从State
作为StateT
的包装器,这也变得更加复杂。 Anyway, we get: 无论如何,我们得到:
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
with a = [Integer]
So, 所以,
runState :: State [Integer] [Integer] -> [Integer] -> ([Integer], [Integer])
get :: MonadState [Integer] (State [Integer]) => State [Integer] [Integer]
And since the constraint is satisfied: 并且因为满足约束:
runState :: State [Integer] [Integer] -> [Integer] -> ([Integer], [Integer])
get :: State [Integer] [Integer]
And now we can see the involved ground types. 现在我们可以看到所涉及的地面类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.