我還在開始探索Haskell。我知道這個代碼在IO
monad中「運行」。當它從l <- ...
行到下一行時,調用IO - bind
。爲什麼這不是懶惰
有人可能會認爲,因爲哈斯克爾是懶惰,l
永遠不會被評估。但是「bind
」總是評估先前的命令,對嗎?因爲該程序會產生「文件未找到」錯誤。
main = do
l <- mapM readFile [ "/tmp/notfound" ]
return()
我還在開始探索Haskell。我知道這個代碼在IO
monad中「運行」。當它從l <- ...
行到下一行時,調用IO - bind
。爲什麼這不是懶惰
有人可能會認爲,因爲哈斯克爾是懶惰,l
永遠不會被評估。但是「bind
」總是評估先前的命令,對嗎?因爲該程序會產生「文件未找到」錯誤。
main = do
l <- mapM readFile [ "/tmp/notfound" ]
return()
有人可能會認爲,因爲Haskell是惰性的,則L是永遠不會計算。
是的,它永遠不會被評估。但是,由於(>>=)
在IO
中的定義,執行了動作readFile "/tmp/notfound"
,這意味着運行時會嘗試打開文件。如果沒有這樣的文件,則會引發「文件未找到」錯誤。如果有這樣一個文件,它將被打開,但其內容不會被讀取,直到要求。在上面,他們不是要求的,所以內容不會被讀取。
什麼是這裏評估(甚至執行)是產生l
的行動。由於該文件不存在,這會引發錯誤。
如果您展開在你的代碼的do
符號,您可以:
main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return())
所以,是的,l
不會求,但是,這並不意味着調用mapM
不會求。 >>=
總是需要評估它的左操作數,以便至少在某種程度上產生一個值(至少在IO monad和其他想到的monad中)。
'我永遠不會評估' - 嗯?懶惰並不意味着「永遠」,它意味着「尚未」或「只有在實際需要時」。 –
@RobertHarvey是的,但對於非Haskellers,查看源代碼,'l'不再使用。但它被隱式使用,對嗎? – Cartesius00