簡體   English   中英

foldr1 和 Haskell 上的無限列表

[英]foldr1 and infinite list on Haskell

在這本精彩的書中閱讀有關folds的信息,我有一個關於foldr1和那里提出的head'實現的問題,有問題的代碼是:

head' = foldr1 (\x _ -> x)

此代碼適用於無限列表,而foldl1不適用。 關於為什么是這個答案的一個很好的視覺解釋。

考慮到foldr1使用最后一個元素作為累加器,我不太明白它為什么會起作用。 例如:

foldr1 (\x _ -> x) [1..]

這是因為(我認為)惰性評估,即使foldr從列表的最后一個元素(無限)開始,我假設因為 function 沒有使用任何中間結果,只返回第一個元素。

那么,編譯器是否足夠聰明地知道,因為在 lambda function 內部只使用了x ,只返回列表的第一個元素? 即使它應該從頭開始?

相反,做

scanr1 (\x _ -> x) [1..]

將打印無限列表的所有元素而不會結束,我想這是foldr正在做的事情,只是編譯器足夠聰明,不會評估它並返回頭部。

提前致謝。

更新

我找到了一個非常好的答案,可以幫助我更深入地了解 foldr 的工作原理:

https://stackoverflow.com/a/63177677/1612432

foldr1使用最后一個元素作為初始累加器值,但組合 function (\x _ -> x)在其第二個參數中是惰性的。

因此,如果列表非空(更不用說無限),則永遠不需要“累加器”值,因此永遠不需要。

foldr並不意味着它應該從右邊開始,只是操作在右邊分組/關聯/括號。 如果組合 function 在其第二個參數中是嚴格的,則確實需要從右側開始計算,但如果不是 - 則不是。

所以不,這不是關於編譯器是否聰明,而是關於 Haskell 要求這一點的惰性語義。 foldr被定義為

foldr g z [x1,x2,...,xn]  =  g x1 (foldr g z [x2,...,xn])

foldr1 g xs  =  foldr g (last xs) (init xs)

就是這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM