簡體   English   中英

具有頭部功能的Haskell懶惰問題

[英]Haskell laziness question with head function

信息:

在文檔和教程中,它說:默認情況下,“ Haskell很懶”。

他們沒有解釋有關細節,我想知道。

現在我知道如果我寫:

filter odd [1, 2, 3]

在結果顯示或在表達式中使用之前,它不會過濾結果。

我對此有兩個問題:


head功能懶惰嗎?

如果不是,那為什么不偷懶呢?

如果很懶,Haskell編譯器如何知道何時執行該函數?

我舉一個例子:

f a b = head a + head b

f [2, 3] [4, 5]

在這種情況下,從我的角度來看,頭部將不會返回2 + 4。

它將返回某些類型或函數,稍后將在需要時執行。 (如果我在某個地方弄錯了,請糾正我)。

所以我的建議是,當Haskell看到類似“ +”的操作時,它將計算結果。

但這變得更加復雜,因為對於整數,我想如果我寫3 + 5話,它也可以是惰性的。

我懷疑在懶惰的表達式開始計算時是否存在帶有函數的列表,因為很難編寫所有變體。

最后:

f head [1, 2]

可以說,在f函數中,我打印傳遞的變量的類型。

現在,Haskell將如何知道應該傳遞Int 1還是惰性表達式?

謝謝

我認為這里有些混亂,因為有時在兩種不同的情況下使用“懶惰”一詞。

  • 懶惰的語義(與渴望的語義相對)
  • 惰性函數(實際上應稱為非嚴格函數)

關於懶惰與渴望的語義:考慮以下表達式

(\x -> 42) (error "urk!")

當對以上進行評估時,結果是什么?

根據熱切的語義,我們在調用函數之前先評估參數。 結果將是運行時錯誤。

根據惰性語義,我們立即調用該函數。 該過程可以在操作上和符號上理解如下。

從操作上講 ,它傳遞了thunk ,它是一個對象,它描述尚未評估的參數,並且在需要參數x時將“強制”(評估)該對象。 我們可以假裝x指向未error "urk!"表達式error "urk!" ,將在需要x時進行評估。

從符號上講,我們使用數學技巧:我們使用稱為“底部”的特殊值來表示錯誤,並稱該error "urk!" 具有這樣的最低價值。 然后,我們簡單地假裝可以傳遞這個非凡的價值。 在上面的函數調用中, x將綁定到“底部”,就好像它是一個正常值一樣。 可以說這很簡單,因為我們不需要關注表達式的求值方式,而只需關注底部的傳播方式。

更准確地說,我們讓“底部”代表運行時錯誤和非終止(無限遞歸),這兩者都使程序擺脫了返回實際結果的麻煩。

例如,我們有一個if bottom then .. else .. ,那if bottom then .. else ..總會產生底部。 同樣適用於bottom + 4 (即bottom)。 再次, case bottom of SomeConstructor -> ...; ... case bottom of SomeConstructor -> ...; ...是最下面的(嗯,除了newtypes ,但是我們忽略它)。 相反f bottom可能會或可能不會按照什么是底部f做:如果它需要的參數,其結果將是底部。

關於惰性(非嚴格)功能。 如果f bottom是bottom,則有時將函數f稱為“惰性”(或更恰當地說,是非嚴格的)。

例如:

f x = x+1  -- strict / non lazy
f x = 5    -- non strict / lazy
head xs = case xs of   -- strict / non lazy
   [] -> error "head: empty list"
   (x:xs) -> x
g x = (x,True)   -- non strict / lazy

因此,因為head bottom是作為case bottom of ...底部,所以head不懶惰。 在操作上,由於head在產生結果之前要求其論點,因此它是嚴格/非惰性的。

關於g :惰性語義的主要特征是像對構造函數(,)這樣的data構造函數本質上是惰性的。 也就是說(bottom, 4)與bottom不同:即使第一對分量是“錯誤”值snd (bottom, 4) = 4也可以使snd (bottom, 4) = 4

因此, g bottom = (bottom, True)不是底部,我們可以應用snd提取True而不觸發錯誤。

head功能懶惰嗎?

是的,Haskell在默認情況下會延遲評估。

如果很懶,Haskell編譯器如何知道何時執行該函數?

當需要該值時,將對函數進行評估-據我了解,最終會在您以某種方式涉及IO時發生。

在這種情況下,從我的角度來看,頭部將不會返回2 + 4。

正確,返回的“值”是所謂的thunk ,這是尚未求值的表達式的另一個名稱。 什么意思 head a + head b

懶惰評估規則的主要例外是IO ,它很受評估。 因此,如果您想打印調用f [2, 3] [4, 5] ,那么將對足夠多的表達式求值以產生要打印的結果。

如果需要,有一些方法可以強制更早進行評估,例如通過使用seq 這有時可能很重要,因為這些重擊可能會變大。

暫無
暫無

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

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