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
表示对于某些monadm
存储类型为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
表示monadm
支持状态类型为s
的状态操作。因此,MonadState s m=>s->m()
是一个函数,它接受类型为s
的值,并返回一个多态值,表示支持对类型为s
的状态进行状态操作的任何monadget
读作“对于支持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]