8

我仍在开始探索 Haskell。我知道这段代码在IOmonad 中“运行”。当它从l <- ...一行转到下一行时,IO - bind就会调用 。

人们可能会认为,因为 Haskell 是惰性的,所以l永远不会评估。但是 " bind" 总是评估前一个命令,对吗?因为程序会产生“file-not-found”错误。

main = do
    l <- mapM readFile [ "/tmp/notfound" ]
    return ()
4

2 回答 2

15

人们可能会认为,因为 Haskell 是懒惰的,所以 l 永远不会被评估。

是的,它永远不会被评估。但是,由于(>>=)in的定义IO,动作readFile "/tmp/notfound"被执行,这意味着运行时尝试打开文件。如果没有这样的文件,则会引发“找不到文件”错误。如果有这样的文件,它会被打开,但它的内容在被要求之前不会被读取。在上面,它们不是必需的,因此不会读取内容。

这里评估(甚至执行)的是产生l. 由于该文件不存在,因此会引发错误。

于 2012-12-01T20:40:17.133 回答
9

如果您do在代码中扩展符号,您会得到:

main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return ())

所以是的,l从未评估过,但这并不意味着mapM从未评估过调用。>>=总是需要评估它的左操作数以便至少在某种程度上产生一个值(至少在 IO monad 和任何其他想到的 monad 中)。

于 2012-12-01T20:42:50.360 回答