为什么我无法获得增加的柜台价值?

| 我正在尝试在Haskell中使用monad进行全局计数,我想每次使用monad计数器时都获得递增的值,但是每次都获得相同的值实在令人困惑! 代码列表如下:
module CounterMonad where

data Counter a = C (Int -> (Int, a))

--reset the counter
new :: Counter ()
new = C $ \\_ -> (0, ())

-- increment the counter:
--inc :: Counter Int
--inc = C $ \\n -> (n+1, n)
inc = get >>= \\s -> (put (s+1))

-- returning the current value of the counter
get :: Counter Int
get = C $ \\n -> (n, n)

--
put x = C $ \\n -> (x, x)

--return is nop, >>= is sequential exectuion
instance Monad Counter where
    return r = C $ \\n -> (n, r)
    (>>=) (C f) g = C $ \\n0 -> let (n1, r1) = f n0
                                   C g\' = g r1
                               in g\' n1

run :: Counter a -> a
run (C f) = snd (f 0)


tickC  = do
  inc
  c <- get
  return c
当我尝试以
run tickC
执行时,它总是返回1。 我想要的是每次我
run tickC
,它都会返回递增的值,例如1,2、3、4...。 我知道那里肯定有一些愚蠢的问题,你们能指出如何吗?     
已邀请:
        这是正确的行为。每次调用
run tickC
时,
run
函数都会将计数器设置为零来评估操作。本质上,每次调用“ 4”时,您将获得一个不同的\“副本\”计数器,该计数器初始化为零。 如果希望每次使计数器递增,则必须在对
run
的同一调用中执行所有操作。例如,
tickMany = do
    x <- tickC
    y <- tickC
    z <- tickC
    return [x, y, z]

> run tickMany
[1, 2, 3]
这对所有单子都是如此,包括ѭ8igno(忽略“ unsafe”操作)。因为执行
IO
操作的唯一方法是通过
main
,所以
IO
monad会穿过使用它的每个函数。 因此,如果您要使用全局计数器,则该计数器必须由全局使用的monad管理(即,每个需要访问它的功能)。您可以全局使用
Counter
monad,也可以将计数器放在the8ѭmonad中。将这样的状态放在自己的monad中似乎是可接受的设计实践,但是当然,这取决于应用程序,
IO
也可以。 您可能还希望查看
Control.Monad.State
,它使您可以使用更少的键入量来定义单子。就像是:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.State
newtype Counter a = Counter (State Int a) deriving (Monad)
...
    

要回复问题请先登录注册