How to implement a global counter using Monad?

2020-02-25 08:35发布

I need a global counter, starting from 0, 1, 2, 3, ..... I kind of understand that this "impure" code should be separately implemented... I am just starting to understand Monad, but have no idea how to implement this global counter using Monad? This could be very useful example for understanding if it is possible

4条回答
成全新的幸福
2楼-- · 2020-02-25 08:41

What you can look into is state monad. This is a general purpose monad which can be used to manage state. In your case the counter is just a state that you want to maintain.

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

查看更多
▲ chillily
3楼-- · 2020-02-25 08:44

You can implement this using a State monad, which stores the current value of your counter as the state. You can then use get to get the current counter value, and modify (+1) to increment it.

One useful variation of this is the Supply monad, where you can use an arbitrary sequence as your "counter", so to have a plain counter starting from zero, just use [0..] as the supply.

查看更多
Evening l夕情丶
4楼-- · 2020-02-25 08:44

While State is fine, you don't need to inspect the counter while calculating, but just to increase it, so the Writer monad should be sufficient. See Learn you a Haskell for a (not too serious) introduction.

查看更多
老娘就宠你
5楼-- · 2020-02-25 08:45

State monad gives you state but only inside the monad. It is not persistent across repeated invocations of the function.

If you want truly global, mutable state you might want to do something like:

  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

Here 'makeCounter' creates a global, mutable variable that is keeps its state across invocations and destroys purity. For example, in the main function two identical calls to 'testCounter' gives different results.

> main
[1,2,3]
[4,5,6]
查看更多
登录 后发表回答