简体   繁体   English

State的`put`和`get`函数

[英]State's `put` and `get` functions

I'n looking at the State Monad 's put and get : I'n看国家单子putget

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. 我不清楚sm的类型是什么。

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? 能否请您解释一下同putget的例子吗?

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状态, getm中的一个动作,它返回一个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 : getput这种组合很常见,有自己的名字, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM