哈斯克尔中状态单体的增量函数



我有以下定义的状态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?

最新更新