foo s1 s2 = null ([x | x <- s2, x == s1])
請說明這個功能什么時候結束?
Haskell 會先遍歷整個串列然后檢查null,還是當一個元素出現時,他會檢查null并完成迭代?如果是第一種選擇,那怎么能更懶惰呢?
uj5u.com熱心網友回復:
Haskell 將首先遍歷整個串列,然后檢查
null.
沒有。null檢查它是否是一個空串列,并回傳True一個空的串列[],以及False對(:)資料的構造。“舊”null實作為 [src]:
null :: [a] -> Bool null [] = True null (_:_) = False
因此,它會將串列理解評估為頭部范式(HNF),一旦它知道外部資料建構式,它就可以回傳True或者False:它不會檢查第一個元素是什么,所以如果這是一個昂貴的運算式,它不會浪費時間在那一個。
“新”null實作為 [src]:
null :: t a -> Bool null = foldr (\_ _ -> False) True
其中foldr串列實作為 [src]:
foldr k z = go where go [] = z go (y:ys) = y `k` go ys
因此,它也將簡單地檢查外部資料建構式是空串列[]還是“缺點”,(:)因為在這種情況下k回傳True并且對引數不感興趣。
串列推導式也是惰性的:它們只會在必要時評估外部資料建構式,并在必要時構造頭部和尾部。您的串列理解被去除為:
concatMap (\x -> if x == s1 then [x] else []) s2
如果它因此必須評估串列的外部資料建構式,它將迭代s2,如果x == s1然后它將產生作為外部資料建構式的“cons”,然后null可以使用它來確定串列是否為空。
這意味著從它x從s2where找到一個元素的那一刻起x == s1,它就會回傳False。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/351368.html
