Haskell 州';s'put'和'get'函数

Haskell 州';s'put'和'get'函数,haskell,Haskell,我正在看“的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]) 在get的类型签名:MonadState s m=>ms中,[1,2,3]如何具有MonadState s m的类型?我不清楚s和m的类型 另外

我正在看“的
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])
get
的类型签名:
MonadState s m=>ms
中,
[1,2,3]
如何具有
MonadState s m
的类型?我不清楚
s
m
的类型

另外,你能说更多关于如何使用
put

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


总的来说,我似乎不明白MonadState s m是什么。请您用
put
get
示例解释一下好吗?

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

get :: MonadState s m => m s
表示对于某些monad
m
存储类型为
s
的某些状态,
get
m
中的一个操作,返回类型为
s
的值。这是相当抽象的,因此让我们使用
State
的重载较少的版本使其更加具体:

现在假设我们想使用
State
来保存一个简单的计数器。让我们使用
execState
而不是
runState
,这样我们可以只关注状态的最终值。我们可以
获取
计数器的值:

> execState get 0
0
我们可以使用
put
设置计数器的值:

> execState (put 1) 0
1
我们可以多次设置状态:

> execState (do put 1; put 2) 0
2
我们可以根据其当前值修改状态:

> execState (do x <- get; put (x + 1)) 0
1
MonadState
是具有状态的monad的类型类<代码>状态是该类的实例:

instance MonadState s (State s) where
  get = Control.Monad.Trans.State.get
  put = Control.Monad.Trans.State.put
还有
StateT
(state monad transformer,它将状态添加到另一个monad)和其他各种变量。引入这种重载是为了,如果您使用的是一堆monad转换器,则不需要在不同的转换器之间显式地执行
提升操作。如果不这样做,可以使用
transformers
中的简单操作


下面是另一个示例,说明如何使用
状态
将变量映射封装为
数据。映射

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
import Control.Monad.Trans.State
导入符合条件的数据。映射为M
动作=做
修改(M.插入“x”2)--x=2
修改(M.插入“y”3)--y=3
x
在get的类型签名:MonadState s m=>ms中,[1,2,3]如何
一种MonadState s m?我不清楚s和s的类型
我是

函数
runState
有两个参数:第一个是要运行的
State
操作,第二个是初始状态。因此,由于初始状态是
[1,2,3]
,这是一个整数列表(*),因此状态类型
s
只是
[Integer]

(*)实际上,
[1,2,3]:

因此,我们看到
runState
专门用于

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
现在,关于第一个论点:

get :: MonadState s m => m s
我们必须有
ms=states sa
,因为我们要将它传递给
runState
,后者需要这样的类型。因此:

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState s m => m s
with m s = State [Integer] a
后一个方程式可简化如下:

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState s m => m s
with m = State [Integer]
and  s = a
替换
s

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a m => m a
with m = State [Integer]
替换
m

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
现在,只有当
a=[Integer]
时,才满足约束
MonadState a(State[Integer])
。这很难看出,因为
MonasState
type类利用函数依赖性强制该类中的每个monad只有一个相关的状态类型。由于
State
StateT
的包装,这一点也变得更加复杂。无论如何,我们得到:

runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
with a = [Integer]
所以

既然满足了约束条件:

runState :: State [Integer] [Integer] -> [Integer] -> ([Integer], [Integer])
get :: State [Integer] [Integer]

现在我们可以看到涉及的地面类型。

MonadState
是一个类型类。没有值具有类型
MonadState s m
MonadState s m
表示monad
m
支持状态类型为
s
的状态操作。因此,
MonadState s m=>s->m()
是一个函数,它接受类型为
s
的值,并返回一个多态值,表示支持对类型为
s
的状态进行状态操作的任何monad
get
读作“对于支持s类型状态操作的所有m,我们有一个类型为
MS
——即生成当前状态的monad操作。”默认值通常是
整数,而不是
Int
@rjanJohansen Right。改编。你在最后一秒错过了一个
get
@ØrjanJohansen谢谢。谢谢你的详细回答。你为什么选择
M而不是
M.lookup
?@KevinMeredith:没问题。我只是不想为这样一个小例子处理
也许
。实际上,我避免在自己的代码中抛出异常函数。
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
runState :: State [Integer] a -> [Integer] -> (a, [Integer])
get :: MonadState a (State [Integer]) => State [Integer] a
with a = [Integer]
runState :: State [Integer] [Integer] -> [Integer] -> ([Integer], [Integer])
get :: MonadState [Integer] (State [Integer]) => State [Integer] [Integer]
runState :: State [Integer] [Integer] -> [Integer] -> ([Integer], [Integer])
get :: State [Integer] [Integer]