所以,Haskell seq函數強制評估它的第一個參數並返回第三個參數。因此它是一箇中綴操作符。如果你想強制對錶達式進行評估,直覺上這樣的特徵將是一元運算符。所以,與其如何使用Haskell的seq?
seq :: a -> b -> b
這將是
seq :: a -> a
因此,如果你想要的值是a
,爲什麼返回b
,你如何構建的b
回報。顯然,我沒有想到Haskell。 :)
所以,Haskell seq函數強制評估它的第一個參數並返回第三個參數。因此它是一箇中綴操作符。如果你想強制對錶達式進行評估,直覺上這樣的特徵將是一元運算符。所以,與其如何使用Haskell的seq?
seq :: a -> b -> b
這將是
seq :: a -> a
因此,如果你想要的值是a
,爲什麼返回b
,你如何構建的b
回報。顯然,我沒有想到Haskell。 :)
想想a `seq` b
不在於它「評估a
」,但它創造a
和b
之間的依賴關係,因此,當你去評估你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
的累積值和遞歸調用之間進行。通過這種方式,當您評估最終表達式(即通過總結列表獲得的數字)時,它會嚴格評估中間值(即您在列表中摺疊的部分總和)。
現在我正在考慮由'seq'創建的依賴關係至少在如上所述'foldl'的情況下是多餘的,因爲正則'foldl'已經通過使用它而在'z''上施加了這樣的依賴約束。 。它似乎。 – George
@George'foldl(\ x y - > 1)undefined [2]'評估爲1,而不是試圖評估undefined。相比之下,使用'foldl'錯誤,因爲它確實評估它。 – chi
@George您在其他語言中習慣使用的不適用於Haskell的特性之一是:函數應用程序不明顯地「使用」應用程序中的所有參數。特別是,僅僅因爲應用程序'foldl'f z'xs'具有'z''作爲參數並不一定*(即沒有檢查'foldl''的定義)意味着使用了'z''。這就是你使用'z''的參數落在哪裏:'z''是一個函數的參數,因此不一定使用。 –
如果你看一下[foldl''](https://wiki.haskell.org/Seq)的[(非常不好格式化的)定義),你會發現你通常只想嚴格評估一些let-bound變量在'a'中,你輸入你的'b'值。 – 2016-09-22 17:23:38