Мне нужен глобальный счетчик, начиная с 0, 1, 2, 3,..... Я понимаю, что этот "нечистый" код должен быть реализован отдельно... Я только начинаю понимать Monad, но понятия не имею, как реализовать этот глобальный счетчик с помощью Monad? Это может быть очень полезным примером для понимания, если это возможно.
Как реализовать глобальный счетчик с помощью Monad?
Ответ 1
Государственная монада дает вам состояние, но только внутри монады. Это не является постоянным при повторных вызовах функции.
Если вы хотите действительно глобальное изменчивое состояние, вы можете сделать что-то вроде:
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]
Ответ 2
Вы можете реализовать это, используя монаду State
, которая сохраняет текущее значение вашего счетчика как состояние. Затем вы можете использовать get
, чтобы получить текущее значение счетчика, и modify (+1)
, чтобы увеличить его.
Одним из полезных вариантов этого является монада Supply
, где вы можете использовать произвольную последовательность в качестве своего "счетчика", чтобы иметь простой счетчик, начиная с нуль, просто используйте [0..]
в качестве источника.
Ответ 3
То, что вы можете посмотреть, это государственная монада. Это общая монада, которая может использоваться для управления состоянием. В вашем случае счетчик - это просто состояние, которое вы хотите сохранить.
Ответ 4
В то время как состояние в порядке, вам не нужно проверять счетчик при расчете, но только для его увеличения, поэтому Writer monad должна быть достаточным. См. Узнайте о вас Haskell для (не слишком серьезного) введения.