[英]To what extent is Haskell lazy?
我需要對Haskell的懶惰做一些澄清。
如果我有這個功能:
myFunction arg
| arg == 1 = a
| arg == 2 = a*b
| arg == 3 = b+c
| otherwise = (a+b)*c
where
a = ...
b = ...
c = ...
d = ...
當我調用myFunction 1
,Haskell將只評估a = ...
函數,既不是b也不是c ,也不是d 。
但如果我寫
myFunction arg
| arg == 1 = a
| arg == 2 = a*b
| arg == 3 = b+c
| otherwise = (a+b)*c
where
(a,b,c,d) = anotherFunction arg
Haskell的行為是什么?
anotherFunction
嗎? anotherFunction
結果嗎? 在這兩種情況下,除非要求該值,否則它不會評估任何內容。 苛刻的值的一種方法是在調用該ghci中函數(它打印在值ghci
,因此,要求它)。 假設您正在執行該函數,那么在第二種情況下,它將元組評估為弱頭正規形式(WHNF) ,然后計算(a,b,c,d)
的第一個元素,因為只需要該值。 其他元素b
, c
和d
將采用thunk形式。 事實上,您可以自己驗證:
myFunction arg
| arg == 1 = a
| arg == 2 = a*b
| arg == 3 = b+c
| otherwise = (a+b)*c
where
(a,b,c,d) = anotherFunction arg
anotherFunction x = (x, undefined, undefined, undefined)
演示ghci:
λ> myFunction 1
1
好吧它只對a
感興趣,所以這意味着有一個隱含的函數 :
thea :: (a,b,c,d) -> a
thea (a,_,_,_) = a
換句話說,Haskell對元組的其他元素不感興趣 。 然而,有時元組的元素共享一些結構。 假設另一個函數定義為:
anotherFunction :: Int -> (Int,Int,Int,Int)
anotherFunction x = (z,t,f,g)
where f = x*x
g = f+x
z = g-2
t = 3
在這種情況下 - 為了評估第一個元素 - 還將評估第三個和第四個元素。 但由於你不對它們做任何事情,Haskell對它們的結果不會特別感興趣。
正如其他人已經指出的那樣,只有a
會進行評估。
但請記住,為了利用懶惰,在評估其組件之前, anotherFunction
返回一個元組是至關重要的。 例如,考慮一下
anotherFunction n = if p > 1000 then (n, p) else (n, 0)
where p = product [1..n]
以上將始終評估product [1..n]
,即使調用者只需要第一對組件(即n
)。 這是因為在返回對之前需要評估if
,並強制p
。 相比之下,
anotherFunction n = (n, if p > 1000 then p else 0)
where p = product [1..n]
將立即返回該對。 如果僅評估其第一個組件,則根本不會計算p
。
除非需要獲取該變量的值,否則不會對其進行求值。 基本上Haskell是如此懶惰,除非被告知不是這樣。
您可以像這樣確認一下
Prelude> :set +m
Prelude> let anotherFunction = (100, 1 `div` 0)
Prelude|
Prelude> let myFunction arg
Prelude| | arg == 1 = a
Prelude| | otherwise = b
Prelude| where
Prelude| (a, b) = anotherFunction
Prelude|
這里, 1 `div` 0
將提高divide by zero
誤差。 如果它評估所有元素,那么即使你用1
調用myFunction
,你也會得到那個錯誤,但是
Prelude> myFunction 1
100
只有當您使用任何其他值調用它時,才需要計算元組的第二個值,並且它將失敗並且divide by zero
錯誤。
Prelude> myFunction 2
*** Exception: divide by zero
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.