0

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

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

4

1 回答 1

7

下面有一个可怕的例子。你被警告了。

考虑伪代码:

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

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

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。它使用递归定义来模拟 while 循环loop,这还不错。但它在任何地方都使用 IO,包括用于模仿命令式可变变量。

更好的方法可能是删除那些IORefs。

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 分开。这是因为它通常会导致更好、更简单且不易出错的代码。

于 2017-02-13T22:28:13.790 回答