Как реализовать глобальный счетчик с помощью Monad? - PullRequest
12 голосов
/ 10 июня 2011

Мне нужен глобальный счетчик, начиная с 0, 1, 2, 3, ..... Я вроде понимаю, что этот "нечистый" код должен реализовываться отдельно ... Я только начинаю понимать Monad, нопонятия не имеете, как реализовать этот глобальный счетчик с помощью Monad?Это может быть очень полезным примером для понимания, если это возможно

Ответы [ 4 ]

8 голосов
/ 15 июня 2011

Государственная монада дает вам состояние, но только внутри монады.Он не является постоянным при повторных вызовах функции.

Если вы хотите действительно глобальное, изменяемое состояние, вы можете сделать что-то вроде:

  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

Здесь 'makeCounter' создает глобальную переменную, которая сохраняет свое состояние при вызовах и уничтожаетчистота.Например, в основной функции два идентичных вызова testCounter дают разные результаты.

> main
[1,2,3]
[4,5,6]
6 голосов
/ 13 сентября 2011

Вы можете реализовать это, используя монаду State, которая хранит текущее значение вашего счетчика в качестве состояния.Затем вы можете использовать get, чтобы получить текущее значение счетчика, и modify (+1), чтобы увеличить его.

Один из возможных вариантов этого - Supply монада , где вы можете использоватьпроизвольная последовательность в качестве вашего «счетчика», поэтому для получения простого счетчика, начинающегося с нуля, просто используйте [0..] в качестве источника.

5 голосов
/ 10 июня 2011

То, что вы можете посмотреть, это государственная монада.Это монада общего назначения, которую можно использовать для управления состоянием.В вашем случае счетчик - это просто состояние, которое вы хотите сохранить.

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

2 голосов
/ 10 июня 2011

Несмотря на то, что с State все в порядке, вам не нужно проверять счетчик при расчете, а просто увеличивать его, поэтому достаточно монады Writer . См. Изучение вас на Haskell для ознакомления (не слишком серьезного).

...