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
Haskell IORef-答案与获取答案的函数_Haskell_Io_Closures_Do Notation_Ioref - Fatal编程技术网

Haskell IORef-答案与获取答案的函数

Haskell IORef-答案与获取答案的函数,haskell,io,closures,do-notation,ioref,Haskell,Io,Closures,Do Notation,Ioref,我正在试图了解IORefs是如何真正被使用的,我很难遵循我在上找到的示例代码 newCounter::IO(IO Int) newCounter=do r您可以将IO视为一种程序newCounter::IO(IO Int)是一个输出程序的程序。更准确地说,newCounter分配一个新计数器,并返回一个程序,该程序在运行时递增计数器并返回其旧值newCounter不执行它返回的程序。如果你改写: newCounter :: IO (IO Int) newCounter = do r <

我正在试图了解
IORefs
是如何真正被使用的,我很难遵循我在上找到的示例代码

newCounter::IO(IO Int)
newCounter=do

r您可以将
IO
视为一种程序
newCounter::IO(IO Int)
是一个输出程序的程序。更准确地说,
newCounter
分配一个新计数器,并返回一个程序,该程序在运行时递增计数器并返回其旧值
newCounter
不执行它返回的程序。如果你改写:

newCounter :: IO (IO Int)
newCounter = do 
  r <- newIORef 0
  let p = do              -- name the counter program p
        v <- readIORef r
        writeIORef r (v + 1)
        return v
  p          -- run the counter program once
  return p   -- you can still return it to run again later
在最终版本中,您可以看到,
printCounts
实际上分配了一个计数器并将其递增三次,打印每个中间值


一个关键步骤是let替换1,其中计数器程序被复制,这就是为什么它要运行三次<代码>设x=p
不同于
x旁注:您不应该有
IO(IO Int)
type,这是一种糟糕的样式。@AJFarmar,我看不出这种样式有什么不好的地方;它只是提供了一个带有受限接口的计数器。好吧,我想实际上最好提供一个抽象的
计数器
类型…让lambda绑定返回。:)@AJFarmar我不会仅仅为了计数器而使用
IO(IO Int)
:但这种模式通常是表达某种东西的最佳方式。
newCounter :: IO (IO Int)
newCounter = do 
  r <- newIORef 0
  let p = do              -- name the counter program p
        v <- readIORef r
        writeIORef r (v + 1)
        return v
  p          -- run the counter program once
  return p   -- you can still return it to run again later
-- original definition
printCounts :: IO ()
printCounts = do
  c <- newCounter
  print =<< c
  print =<< c
  print =<< c

-- by definition of newCounter...

printCounts = do
  c <- do
    r <- newIORef 0
    return $ do
      v <- readIORef r
      writeIORef r (v + 1)
      return v
  print =<< c
  print =<< c
  print =<< c

-- by the monad laws (quite hand-wavy for brevity)
-- do
--   c <- do
--     X
--     Y
--   .....
-- =
-- do
--   X
--   c <- 
--     Y
--   .....
--
-- (more formally,
--  ((m >>= \x -> k x) >>= h) = (m >>= (\x -> k x >>= h)))

printCounts = do
  r <- newIORef 0
  c <-
    return $ do
      v <- readIORef r
      writeIORef r (v + 1)
      return v
  print =<< c
  print =<< c
  print =<< c

-- c <- return X
-- =
-- let c = X
--
-- (more formally, ((return X) >>= (\c -> k c)) = (k X)

printCounts = do
  r <- newIORef 0
  let c = do
        v <- readIORef r
        writeIORef r (v + 1)
        return v
  print =<< c
  print =<< c
  print =<< c

-- let-substitution

printCounts = do
  r <- newIORef 0
  print =<< do
        v <- readIORef r
        writeIORef r (v + 1)
        return v
  print =<< do
        v <- readIORef r
        writeIORef r (v + 1)
        return v
  print =<< do
        v <- readIORef r
        writeIORef r (v + 1)
        return v

-- after many more applications of monad laws and a bit of renaming to avoid shadowing
-- (in particular, one important step is ((return v >>= print) = (print v)))

printCounts = do
  r <- newIORef 0
  v1 <- readIORef r
  writeIORef r (v1 + 1)
  print v1
  v2 <- readIORef r
  writeIORef r (v2 + 1)
  print v2
  v3 <- readIORef r
  writeIORef r (v3 + 1)
  print v3