我想使用monad在haskell中编写一个循环,但我很难理解这个概念。
有人可以为我提供一个简单的while循环示例,同时满足一些涉及IO操作的条件吗?我不想要一个抽象的例子,而是一个真正具体的例子。
答案 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分开。这是因为它通常会导致更好,更简单,更不容易出错的代码。