簡體   English   中英

斯卡拉在哈斯克爾的風格

[英]Scala's style val in Haskell

在Scala中,我可以表達一個函數,每次引用它時都會對它進行評估:

def function = 1 + 2 + 3

或僅評估一次的val

val val1 = 1 + 2 + 3

即使我多次打電話。

當然,在Haskell中,我可以定義一個函數(當我調用它時,它會反復評估):

function = 1 + 2 + 3

我可以在Haskell中定義Scala的val模擬嗎?

更新:問題不在於懶惰的評估。

UPDATE2:

將評估function值的次數?

function = 1 + 2 + 3
main = do
        print function
        print function
        print function

Haskell沒有指定很多方法來控制次數或命令事物的評估。也就是說,GHC最多只評估一次CAF (除非它們是類型多態)。 注意,對於(默認)單態限制, function = 1 + 2 + 3function定義為單態CAF,因此function最多被評估一次。

您還會發現許多人反對將此稱為函數,因為除非您做了一些非常奇特的事情,否則它不是一個函數。 (其類型中沒有箭頭。)

你當然可以寫:

let x = 1 + 2 + 3 in ...

代替

let myFunc () = 1 + 2 + 3 in ...

但是在Haskell中,考慮其中任何一個的評估頻率並沒有多大意義,除了如果計算需要它們兩者至少評估一次,從不評估它們。

Haskell和Scala之間的關鍵區別在於,在Scala或任何其他嚴格語言中,綁定形式val x = 1 + 2 + 3告訴Scala評估表達式1 + 2 + 3並將其結果綁定到變量。 在Haskell,另一方面, let x = 1 + 2 + 3的綁定的計算1 + 2 + 3x和時,甚至是否計算表達式的問題是沒有被決定let表達在所有。

由於Haskell綁定表單無法決定與其關聯的表達式進行評估的策略,因此無法編寫Scala版本的精確模擬。

編輯:忽略這個答案。 它只適用於沒有優化的編譯。 以我的斐波納契實現為例, ghc -O0 -ddump-simpl main.hs在Core中給出了一個單獨的fib定義:

Main.fib :: forall a_agB. GHC.Num.Num a_agB => () -> [a_agB]

但是使用O2優化進行編譯ghc -O2 -ddump-simpl main.hs將斐波納契列表實現為頂層的常量值

Main.$wfib :: forall a_agG. GHC.Num.Num a_agG => [a_agG]

然后由封閉的fibonacci實現調用它(它確實采用a ()參數)

Main.fib =
  \ (@ a_agG) (w_stM :: GHC.Num.Num a_agG) (w1_stN :: ()) ->
    case w1_stN of _ { () -> Main.$wfib @ a_agG w_stM }

結果是,當Main.fib沒有得到記憶時, Main.$wfib仍然會被記憶並占用內存。


原答案如下:

正如丹尼爾瓦格納在另一個答案中所說,這樣的定義

val = 1+2+3

只會評估一次,除非它是多態的。 如果你想在每次引用它時進行評估,你就可以做到

val () = 1+2+3

這樣你就必須將參數()賦予val ,但是它不會保存計算值。 如果val的計算值占用大量內存,但很容易計算,並且在需要時逐步消耗,這可能是一件好事。 例如,您可以擁有斐波那契數字列表:

fib = 0 : 1 : zipWith (+) fib (tail fib)

如果你現在做的話fib !! 100000 fib !! 100000 ,您需要計算所有前100,000個斐波納契數。 fib表示此列表,因此它不能被垃圾收集,但會在內存中掛起。 為了解決這個問題,你可以做到

fib () = let x = 0 : 1 : zipWith (+) x (tail x) in x

由於fib現在是(常量)函數而不是常量值,因此不會保存其值,從而釋放內存。

編輯:正如Philip JF在評論中所說,let表達式的內容可能被一個不友好的編譯器解除,這將導致不必要的共享

暫無
暫無

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

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