2016-09-22 96 views
6

所以,Haskell seq函數強制評估它的第一個參數並返回第三個參數。因此它是一箇中綴操作符。如果你想強制對錶達式進行評估,直覺上這樣的特徵將是一元運算符。所以,與其如何使用Haskell的seq?

seq :: a -> b -> b 

這將是

seq :: a -> a 

因此,如果你想要的值是a,爲什麼返回b,你如何構建的b回報。顯然,我沒有想到Haskell。 :)

+1

如果你看一下[foldl''](https://wiki.haskell.org/Seq)的[(非常不好格式化的)定義),你會發現你通常只想嚴格評估一些let-bound變量在'a'中,你輸入你的'b'值。 – 2016-09-22 17:23:38

回答

15

想想a `seq` b不在於它「評估a」,但它創造ab之間的依賴關係,因此,當你去評估你b評估a以及方式。

例如,這意味着a `seq` a是完全多餘的:當您評估a時,您告訴Haskell評估a。通過相同的邏輯,只有一個參數的seq a與僅僅自己編寫a沒有什麼不同。

只是有seq a,以某種方式評估a將無法​​正常工作。問題是,seq a本身就是一個表達式,可能不會被評估 - 例如,它可能在一些嵌套的thunk中很深。因此,只有在評估整個seq a表達式時,它纔會變得相關 - 在這一點上,無論如何,您本可以自己評估a

@ Rhymoid關於如何嚴格使用它的例子(foldl')很好。我們的目標是寫一個摺疊,使其中間累計值(acc)在我們評估最終結果後立即在每一步完成評估。

foldl' f z (x:xs) = 
    let z' = f z x in z' `seq` foldl' f z' xs 

你可以想像這爲seq在摺疊的f各個應用程序之間的長鏈,它們都連接到最後的結果是:這是通過添加一個seq的累積值和遞歸調用之間進行。通過這種方式,當您評估最終表達式(即通過總結列表獲得的數字)時,它會嚴格評估中間值(即您在列表中摺疊的部分總和)。

+0

現在我正在考慮由'seq'創建的依賴關係至少在如上所述'foldl'的情況下是多餘的,因爲正則'foldl'已經通過使用它而在'z''上施加了這樣的依賴約束。 。它似乎。 – George

+2

@George'foldl(\ x y - > 1)undefined [2]'評估爲1,而不是試圖評估undefined。相比之下,使用'foldl'錯誤,因爲它確實評估它。 – chi

+7

@George您在其他語言中習慣使用的不適用於Haskell的特性之一是:函數應用程序不明顯地「使用」應用程序中的所有參數。特別是,僅僅因爲應用程序'foldl'f z'xs'具有'z''作爲參數並不一定*(即沒有檢查'foldl''的定義)意味着使用了'z''。這就是你使用'z''的參數落在哪裏:'z''是一個函數的參數,因此不一定使用。 –