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
4条答案
按热度按时间zyfwsgd61#
状态monad给你状态,但只在monad内部。它在函数的重复调用中不是持久的。
如果你想要真正全局的、可变的状态,你可能想做一些像这样的事情:
在这里,
makeCounter
创建了一个全局可变变量,它在调用之间保持其状态,并破坏纯度。例如,在main函数中,两个相同的testCounter
调用会给出不同的结果。6tdlim6h2#
您可以使用
State
monad实现这一点,它将计数器的当前值存储为状态。然后可以使用get
获取当前计数器值,并使用modify (+1)
递增计数器值。一个有用的变体是the
Supply
monad,您可以使用任意序列作为“计数器”,因此要有一个从零开始的普通计数器,只需使用[0..]
作为电源。ehxuflar3#
你能看到的是状态单子。这是一个通用的monad,可以用来管理状态。在您的情况下,计数器只是您想要维护的一个状态。
http://www.haskell.org/haskellwiki/State_Monad
kxe2p93d4#
虽然State很好,但您不需要在计算时检查计数器,只需增加它,因此Writer monad应该足够了。请参阅Learn you a Haskell(不太严重)介绍。