如何使用Monad实现全局计数器?

12 monads haskell

我需要一个全局计数器,从0,1,2,3开始.....我有点明白这个"不纯"的代码应该单独实现......我刚刚开始理解Monad,但是我不知道如何使用Monad实现这个全局计数器?这可能是了解是否可行的非常有用的示例

Dee*_*ech 8

州monad给你状态但只在monad里面.它在函数的重复调用中不是持久的.

如果你想要真正的全局,可变状态,你可能想做类似的事情:

  import Data.IORef

  type Counter = Int -> IO Int

  makeCounter :: IO Counter
  makeCounter = do
      r <- newIORef 0
      return (\i -> do modifyIORef r (+i)
                       readIORef r)

  testCounter :: Counter -> IO ()
  testCounter counter = do
      b <- counter 1
      c <- counter 1
      d <- counter 1
      print [b,c,d]

  main = do
      counter <- makeCounter
      testCounter counter
      testCounter counter
Run Code Online (Sandbox Code Playgroud)

这里'makeCounter'创建了一个全局的,可变的变量,它保持调用状态并破坏纯度.例如,在main函数中,对'testCounter'的两次相同调用会产生不同的结果.

> main
[1,2,3]
[4,5,6]
Run Code Online (Sandbox Code Playgroud)


ham*_*mar 6

您可以使用Statemonad 实现此操作,monad将计数器的当前值存储为状态.然后,您可以使用get获取当前计数器值并modify (+1)增加它.

这方面的一个有用的变化是Supply单子,在这里你可以使用任意序列的"柜台",所以有一个简单的计数器从零开始,只需使用[0..]作为电源.


Ank*_*kur 5

你可以看到的是州monad.这是一个通用monad,可用于管理状态.在您的情况下,计数器只是您想要维护的状态.

http://www.haskell.org/haskellwiki/State_Monad