2012-12-01 64 views
8

我還在開始探索Haskell。我知道這個代碼在IO monad中「運行」。當它從l <- ...行到下一行時,調用IO - bind爲什麼這不是懶惰

有人可能會認爲,因爲哈斯克爾是懶惰l永遠不會被評估。但是「bind」總是評估先前的命令,對嗎?因爲該程序會產生「文件未找到」錯誤。

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

'我永遠不會評估' - 嗯?懶惰並不意味着「永遠」,它意味着「尚未」或「只有在實際需要時」。 –

+1

@RobertHarvey是的,但對於非Haskellers,查看源代碼,'l'不再使用。但它被隱式使用,對嗎? – Cartesius00

回答

15

有人可能會認爲,因爲Haskell是惰性的,則L是永遠不會計算。

是的,它永遠不會被評估。但是,由於(>>=)IO中的定義,執行了動作readFile "/tmp/notfound",這意味着運行時會嘗試打開文件。如果沒有這樣的文件,則會引發「文件未找到」錯誤。如果有這樣一個文件,它將被打開,但其內容不會被讀取,直到要求。在上面,他們不是要求的,所以內容不會被讀取。

什麼這裏評估(甚至執行)是產生l的行動。由於該文件不存在,這會引發錯誤。

9

如果您展開在你的代碼的do符號,您可以:

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

所以,是的,l不會求,但是,這並不意味着調用mapM不會求。 >>=總是需要評估它的左操作數,以便至少在某種程度上產生一個值(至少在IO monad和其他想到的monad中)。