Haskell 中使用 monad 的 while 循环示例

Example of while loop in Haskell using monads

我想使用 monad 在 haskell 中编写一个循环,但我很难理解这个概念。

有人能给我提供一个 while 循环的简单示例,同时满足某些条件并涉及 IO 操作吗?我不想要一个抽象的例子,而是一个真正有效的具体例子。

下面是一个可怕的例子。您已收到警告。

考虑伪代码:

var x = 23
while (x != 0) {
   print "x not yet 0, enter an adjustment"
   x = x + read()
}
print "x reached 0! Exiting"

这是它在Haskell中的piece-by-piece翻译,尽可能使用命令式风格。

import Data.IORef

main :: IO ()
main = do
   x <- newIORef (23 :: Int)
   let loop = do
          v <- readIORef x
          if v == 0
          then return ()
          else do
             putStrLn "x not yet 0, enter an adjustment"
             a <- readLn
             writeIORef x (v+a)
             loop
   loop
   putStrLn "x reached 0! Exiting"

以上确实很恐怖Haskell。它使用 recursively-defined loop 模拟 while 循环,这还不错。但它到处都使用 IO,包括模仿 imperative-style 可变变量。

更好的方法是删除那些 IORef

main = do
   let loop 0 = return ()
       loop v = do
          putStrLn "x not yet 0, enter an adjustment"
          a <- readLn
          loop (v+a)
   loop 23
   putStrLn "x reached 0! Exiting"

无论如何都不是优雅的代码,但至少 "while guard" 现在不会执行不必​​要的 IO。

通常,Haskell 程序员努力尽可能地将纯计算与 IO 分开。这是因为它通常会导致更好、更简单和更少的 error-prone 代码。