Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何使用Monad实现全局计数器?_Haskell_Monads - Fatal编程技术网

Haskell 如何使用Monad实现全局计数器?

Haskell 如何使用Monad实现全局计数器?,haskell,monads,Haskell,Monads,我需要一个全局计数器,从0,1,2,3。。。。。 我有点理解这个“不纯”的代码应该单独执行。。。我刚刚开始理解Monad,但不知道如何使用Monad实现这个全局计数器?这可能是一个非常有用的例子,有助于理解是否可能您可以研究的是状态单子。这是一个通用的monad,可用于管理状态。在您的情况下,计数器只是您想要维护的状态 虽然状态良好,但在计算时不需要检查计数器,只需增加计数器即可,这样就足够了。请参阅以获得(不太严肃的)介绍。State monad提供状态,但仅在monad内部提供。它不会在函数

我需要一个全局计数器,从0,1,2,3。。。。。
我有点理解这个“不纯”的代码应该单独执行。。。我刚刚开始理解Monad,但不知道如何使用Monad实现这个全局计数器?这可能是一个非常有用的例子,有助于理解是否可能

您可以研究的是状态单子。这是一个通用的monad,可用于管理状态。在您的情况下,计数器只是您想要维护的状态


虽然状态良好,但在计算时不需要检查计数器,只需增加计数器即可,这样就足够了。请参阅以获得(不太严肃的)介绍。

State monad提供状态,但仅在monad内部提供。它不会在函数的重复调用中持久化

如果您想要真正的全局、可变状态,您可能需要执行以下操作:

  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

您可以使用
State
monad实现这一点,它将计数器的当前值存储为状态。然后,您可以使用
get
获取当前计数器值,并使用
modify(+1)
将其递增


其中一个有用的变化是,您可以使用任意序列作为“计数器”,因此要有一个从零开始的普通计数器,只需使用
[0..]
作为供应。

我不确定使用编写器是否足够-如果您想在计算过程中了解当前计数,您无法从编写器获取它(仅写状态)它必须是一个状态单子。@stephen tetley这个问题不清楚在计算过程中是否需要计数器值。但是,如果您只需要计数器的最终结果,
编写器
更“安全”,更易于使用。正如Ankur所说,这基本上是一个状态单子。Monad实例的实现--
return
和bind
(>>=)
-将与State相同,但是您需要的更新操作不如State Monad的
put
put
可以以任意方式更改状态)。我建议一个好的接口是
next
,它增加计数并返回新计数。保留一个只查询计数而不更新计数的
get
操作也很好。签出。要获得计数器,只需使用
[0..]
作为补充。@哈马尔您的评论应该是答案,并且应该被接受。为什么您要在
计数器上签名而不是简单地签名
IO Int
> main
[1,2,3]
[4,5,6]