我有以下定义的状态Monad,我正在尝试使用它实现增量函数:
data State a = State (Int -> (a, Int))
instance Monad State where
return x = State $ s -> (x, s)
(State f) >>= k = State $ s ->
let
(x, s') = f s
State f' = k x
in f' s'
get :: State Int
get = State $ s -> (s, s)
put :: Int -> State ()
put s = State $ _ -> ((), s)
我做了以下工作:
increment :: State ()
increment = do
a <- get
put(a+1)
这似乎有效。
这是否正确,如何验证状态是否确实在递增?也许更一般地说,我如何使用get
put
?
你需要一些方法来提取状态的内部函数。您可以通过State a
上的模式匹配来执行此操作,就像在绑定定义中一样,也可以使用记录语法data State a = State {runState :: Int -> (a, Int)}
定义状态。运行状态后,您可以使用 runState increment 1
轻松测试增量函数。你对get和put的使用似乎很好,不太确定你想知道什么。
此外,您应该为 State 添加一个 Applicative 实例,因为 Applicative 将从 ghc 7.10 开始成为 Monad 的超类。
让我们向此代码添加一些实用程序函数:
-- Given a `State` computation and a starting state, run the computation
-- and obtain the result value and final state.
runState :: State a -> Int -> (a, Int)
runState (State f) init = f init
-- Given a `State` computation and a starting state, run the computation
-- and obtain the result value.
evalState :: State a -> Int -> a
evalState st i = fst (runState st i)
-- Given a `State` computation and a starting state, run the computation
-- and obtain the final state.
execState :: State a -> Int -> Int
execState st i = snd (runState st i)
现在,使用这些函数之一,您将如何编写一个函数来测试increment
是否确实将状态递增了 1?