簡體   English   中英

haskell 在處理復雜的程序流程時有多懶惰

[英]how lazy is haskell when dealing with complicated program flow

我想知道 Haskell 有多聰明/懶惰。 我能否始終確定 Haskell 只會執行生成某個 output 所需的操作?

不。

Haskell 為其核心類 lambda 演算指定了指稱語義,您可以依賴該語義。 此外,還有一個元理論證明,一個特定的歸約順序——俗稱“惰性求值”——實現了這種語義; 很多人將其用作 Haskell 程序行為方式的心理 model。

Haskell 程序可能最終評估超出必要的兩種方式:

  • Haskell 實現可以選擇評估更多。 GHC 在大部分地方都使用惰性求值,但我相信在某些情況下它會使用其他求值順序來提高效率。 您還可以查看Eager Haskell項目,它正在嘗試使用另一種實現策略; 或者,原則上,實現將有權選擇推測性地將某些計算分叉到另一個線程(然后在不需要時丟棄結果)。

  • 指定的指稱語義可能需要比“必要”更多的評估。 例如,偶爾會絆倒初學者的一個:

     primes:: [Int] primes = 2: filter prime [3,5..] prime:: Int -> Bool prime x = and [x `mod` p /= 0 | p <- primes, p < x]

    在檢查3是否應該在列表primes中時,實際上沒有必要檢查超過2primes的任何元素,因為該序列是嚴格單調遞增的。 但是 Haskell 不夠聰明(不嘗試)來注意到這一點; 它將 go 直接嘗試檢查primes的 rest 並最終進入無限循環,而不是給出素數列表。

    一個更小的例子:你可以認為x && False總是False ,但x通常會被評估,因為語義表明如果x是,這應該是一個無限循環。 (對比False && x ,這通常不會導致評估x 。)

也就是說,當您說“復雜結構”時,想到的一件事是:即使使用我定義的自定義數據類型, Haskell 也會做懶惰的事情嗎? 也就是說,像 hash 映射和平衡樹和 kd 樹等復雜結構會被延遲處理嗎? 答案是肯定的; 除了IO之外, Prelude中的任何類型都沒有什么特別之處。 列表、布爾值、 Maybe等是惰性的,不是因為編譯器知道關於它們的特殊信息,而是因為 Haskell 指定的縮減規則及其作為類型的聲明。

當然,有一些方法可以選擇退出懶惰。 您將在 Hackage 上看到的一些結構以各種方式做到這一點; 但別擔心,通常這會在他們的文檔中聲明。

暫無
暫無

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

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