为什么不懒惰

时间:2012-12-01 20:28:09

标签: haskell ghc

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

有人可能会认为,因为Haskell lazy ,所以永远不会评估l。但是“bind”总是评估上一个命令,是吗?因为程序产生“文件未找到”错误。

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

2 个答案:

答案 0 :(得分:15)

  

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

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

在此处评估(甚至执行)是生成l的动作。由于该文件不存在,因此会引发错误。

答案 1 :(得分:9)

如果您在代码中展开do表示法,则会得到:

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

所以是的,l永远不会被评估,但这并不意味着永远不会评估对mapM的调用。 >>=始终需要评估其左操作数,以便至少在某种程度上产生一个值(至少在IO monad和任何其他想象的monad中)。