[英]Why does this Haskell statement not evaluate lazily?
我定義了以下函數:
ex 1 x = 1
ex 0 x = 0
ex b x = b ** x
然后,當我執行以下操作時:
1 `ex` (sum [1..])
它試圖計算無限序列的總和,而不是懶惰和返回1.為什么?
編輯:經過進一步調查,我發現如果我在文件中定義ex
函數會發生懶惰,但如果我在GHCI中定義它則不會:
$ ghci
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help
Loading package base ... linking ... done.
Prelude> let ex 1 x = 1
Prelude> let ex b x = b ** x
Prelude> ex 1 (sum [1..])
<interactive>: out of memory (requested 1048576 bytes)
如果我將ex
定義拉入文件(在本例中為test.hs):
$ ghci
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help
Loading package base ... linking ... done.
Prelude> :load test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> ex 1 (sum [1..])
1.0
那么,新問題是為什么?
在GHCi中,每個let
語句都引入了ex
的新定義,而不是您期望的多個模式案例。 所以它掛起是因為,當你之后輸入ex 1 (sum [1..])
,只存在最終的ex bx = b ** x
版本。
如果要在GHCi中定義具有多個模式案例的函數,則需要將其放在單個let
語句中,如下所示:
let ex 1 x = 1; ex 0 x = 0; ex b x = b ** x
這同樣適用於其他任何東西,通常會在多個線路,如被寫do
記號。 例如,這樣的函數:
f x = do
y <- get
put (x + y)
return y
必須在GHCi中這樣寫:
let f x = do { y <- get; put (x + y); return y }
Prelude> let ex 1 x = 1
Prelude> let ex b x = b ** x
你沒有在這里定義一個包含兩種情況的函數。 您可以使用一個案例定義一個函數,然后再次定義它,覆蓋先前的定義。
要使用兩個模式定義一個函數,請使用let ex 1 x = 1; ex bx = b ** x
let ex 1 x = 1; ex bx = b ** x
,即用分號分隔案例。
我錯過了一點懶惰,這使得答案低於假。
因為sum
計算序列中所有元素的總和。 在你的情況下,這是無止境的。
你可能想要
map ((curry ex) 1) [1..]
那是
map -- map each item x to y
(
(
curry ex -- curry ex, to transform (x, y) -> z into x -> y -> z
)
1 -- then invoke it with 1, which results in y -> z, x being 1
)
[1..] -- the infinite sequence to be mapped.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.