How to implement a global counter using Monad?

前端 未结 4 1209
[愿得一人]
[愿得一人] 2020-12-30 07:09

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

相关标签:
4条回答
  • 2020-12-30 07:38

    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.

    0 讨论(0)
  • 2020-12-30 07:41

    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]
    
    0 讨论(0)
  • 2020-12-30 07:45

    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.

    0 讨论(0)
  • 2020-12-30 07:57

    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

    0 讨论(0)
提交回复
热议问题