Bu yaygın olarak bilinmemektedir, ancak foldl'
aslında kendi akümülatör argümanında katı değildir! türünü hatırlayın:
foldl' :: (a -> b -> a) -> a -> [b] -> a
Eğer const
geçirirseniz Gördüğünüz gibi argüman 2'de Onun katılık, argüman 1 için verilen fonksiyonun katılığından bağlıdır:
Prelude Data.List> foldl' (const (+1)) undefined [1]
2
Prelude Data.List> foldl' (const (+1)) undefined [1..4]
5
Sen safça sanırdım, "foldl 'katı", "akümülatör argümanında katı" anlamına gelir. Yukarıdaki ile çelişiyor. Bununla birlikte, sıkılık sadece döngü durumundaki işlev uygulamasının sonucu olduğu için, daha da sinsi bir durumdur. Bununla birlikte, daha da sinsidir. Yani hala baz durumda girerseniz altları olsun, ama endüktif durum:
Prelude Data.List> foldl' (const (+1)) undefined []
*** Exception: Prelude.undefined
Yani katılık in argument 2da argüman 3'ün değerine bağlı! onun 2 argüman "tam olarak" sıkı:
Bu
ben yazacağınız nasıl. Gördüğünüz gibi, ikinci argüman gerçekten sıkı
foldl' f z0 xs0 = go z0 xs0
where
go !z [] = z
go !z (x:xs) = go (f z x) xs
: Haskell2010 sürümü ile karşılaştırıldığında
Prelude Data.List.Stream> foldl' (\a b -> 1) undefined [undefined]
*** Exception: Prelude.undefined
:
Prelude Data.List.Stream> Data.List.foldl' (\a b -> 1) undefined [undefined]
1
Bu GÜNCEL pratik bir etkisi vardır - Akım tanımı sürekli olarak akümülatör argümanını açmayacak.
Tarihsel Not: Bu, 2007'de akış kitaplığı için liste kitaplığının katılık semantiklerini belirttiğimizde ve Duncan Coutt'un PhD thesis numaralı belgede kesinliği belirtme yaklaşımı verildiğinde keşfedildi.
İki katlama sürümü için kaynak kodu karşılaştırın ve aydınlanmış olabilirsiniz. – augustss
@augustss belki, buna cevap verebilir misiniz? – jackalope
Gördüğünüz gibi, foldl 'ilk argümanı çağırmadan önce hesaplar, katlanırken (genel olarak) gerektiğinde değerlendirilecek bir thunk iletir. – augustss