State的`put`和`get`函数

Kev*_*ith 4 haskell

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

get's类型签名:MonadState s m => m s,有怎样[1,2,3]的类型MonadState s m?目前尚不清楚对我有什么的类型sm是.

另外,您能否详细说明如何使用put

ghci>:t put put :: MonadState sm => s - > m()

总的来说,似乎我不明白是什么MonadState s m.你能解释一下putget例子吗?

Jon*_*rdy 8

MonadState s m是类型类约束,而不是类型.签名:

get :: MonadState s m => m s
Run Code Online (Sandbox Code Playgroud)

说对于一些m存储某种类型状态的monad s,get是一个m返回类型值的动作s.这是非常抽象的,所以让我们使用较少重载的Statefrom transformers:

get :: State s s
put :: s -> State s ()
Run Code Online (Sandbox Code Playgroud)

现在说我们想用来State保持一个简单的计数器.让我们使用execState而不是runState这样我们可以只关注状态的最终值.我们可以get计数器的价值:

> execState get 0
0
Run Code Online (Sandbox Code Playgroud)

我们可以使用put以下方法设置计数器的值:

> execState (put 1) 0
1
Run Code Online (Sandbox Code Playgroud)

我们可以多次设置状态:

> execState (do put 1; put 2) 0
2
Run Code Online (Sandbox Code Playgroud)

我们可以根据其当前值修改状态:

> execState (do x <- get; put (x + 1)) 0
1
Run Code Online (Sandbox Code Playgroud)

的组合getput足够常见的有自己的名称,modify:

> execState (do modify (+ 1)) 0
1

> execState (do modify (+ 2); modify (* 5)) 0
10
Run Code Online (Sandbox Code Playgroud)

MonadState是具有状态的monad类型.State是该类的一个实例:

instance MonadState s (State s) where
  get = Control.Monad.Trans.State.get
  put = Control.Monad.Trans.State.put
Run Code Online (Sandbox Code Playgroud)

所以StateT(状态monad变换器,它将状态添加到另一个monad)和其他各种.引入了这种重载,因此如果您使用的是monad变换器堆栈,则不需要lift在不同的变换器之间进行显式操作.如果你不这样做,你可以使用更简单的操作transformers.


这是另一个如何State用于封装变量映射的示例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
Run Code Online (Sandbox Code Playgroud)