Es ist nicht allgemein bekannt, aber foldl'
ist tatsächlich nicht-strikt in seinem Akku-Argument! Rufen Sie den Typ:
foldl' :: (a -> b -> a) -> a -> [b] -> a
Seine Strenge in Argument 2 ist abhängig von der Strenge der Funktion für Argument 1, wie Sie sehen, wenn Sie const
passieren:
Prelude Data.List> foldl' (const (+1)) undefined [1]
2
Prelude Data.List> foldl' (const (+1)) undefined [1..4]
5
Sie hätte gedacht, naiv, dass "foldl" streng ist, bedeutet "streng im Akkumulatorargument". Das Obige widerspricht dem.
Allerdings ist es noch heimtückischer, da die Strenge nur auf das Ergebnis der Funktionsanwendung im Cons-Fall der Schleife zurückzuführen ist. So erhalten Sie noch Böden, wenn Sie den Basisfall eintreten, aber nicht die induktive Fall:
Prelude Data.List> foldl' (const (+1)) undefined []
*** Exception: Prelude.undefined
so die Strikt in argument 2auch hängt von der Wert Argumentations 3!
So würde ich es schreiben: "voll" streng in seinem 2. Argument.
foldl' f z0 xs0 = go z0 xs0
where
go !z [] = z
go !z (x:xs) = go (f z x) xs
, die in ihrem zweiten Argument wirklich streng, wie man sehen kann:
Prelude Data.List.Stream> foldl' (\a b -> 1) undefined [undefined]
*** Exception: Prelude.undefined
mit der Version Haskell2010 Vergleich:
Prelude Data.List.Stream> Data.List.foldl' (\a b -> 1) undefined [undefined]
1
Diese actuall eine praktische Wirkung hat - die Die aktuelle Definition wird ihr Akkumulatorargument nicht konsequent auspacken.
Historischer Hinweis: Dies wurde entdeckt, als wir die Striktheitssemantik der Listenbibliothek für das Stream Fusion Paper im Jahr 2007 spezifizierten, und der Ansatz zur Spezifizierung der Strenge ist in Duncan Coutts PhD thesis angegeben.
Vergleichen Sie den Quellcode für die beiden Versionen von Foldl, und Sie könnten aufgeklärt werden. – augustss
@augustss vielleicht, können Sie das beantworten? – jackalope
Wie Sie sehen können, berechnet foldl 'das erste Argument für lgo vor dem Aufruf, während foldl (im Allgemeinen) ein Thunk übergibt, das bei Bedarf ausgewertet wird. – augustss