Haskell中使用monads的while循环示例

时间:2017-02-13 21:35:06

标签: loops haskell while-loop monads io-monad

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

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

1 个答案:

答案 0 :(得分:4)

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

考虑伪代码:

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。它使用递归定义的loop模拟while循环,这不是太糟糕。但它在任何地方都使用IO,包括模仿命令式风格的可变变量。

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