为什么不懒惰

Car*_*s00 8 haskell ghc

我还在开始探索Haskell.我知道这个代码在IOmonad中"运行" .当它从l <- ...行到下一行时,IO - bind调用它.

人们可能会认为,因为Haskell 很懒,所以l从未评估过.但是" bind"总是评估上一个命令,是吗?因为程序产生"文件未找到"错误.

main = do
    l <- mapM readFile [ "/tmp/notfound" ]
    return ()
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 15

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

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

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


sep*_*p2k 9

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

main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return ())
Run Code Online (Sandbox Code Playgroud)

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