2013-01-11 26 views
5

Takip < Gerçek Dünya Haskell >, foldl'foldl sıkı versiyonu söylenir.Haskell sıkı versiyonunun anlamı nedir?

Ama beni anlamak için zor strict ne demek ??

foldl f z0 xs0 = lgo z0 xs0 
     where 
      lgo z []  = z 
      lgo z (x:xs) = lgo (f z x) xs 


foldl' f z0 xs0 = lgo z0 xs0 
    where lgo z []  = z 
      lgo z (x:xs) = let z' = f z x in z' `seq` lgo z' xs 
+2

İki katlama sürümü için kaynak kodu karşılaştırın ve aydınlanmış olabilirsiniz. – augustss

+0

@augustss belki, buna cevap verebilir misiniz? – jackalope

+0

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

cevap

6

foldl ve (katı) foldl' anlama sahip yakındır. Fark, özellikle de büyük bir listeyi çevirirken performansta. tembellik bir thunk ve foldl binanın bir yüke sahiptir' çok büyük bir thunk oluşturmak değil çünkü o sonuca varmak için daha etkili bir yoldur. Haskell Wiki

Sıkı fonksiyonları üzerindeki ayrıntılı olarak açıklayan gerçekten iyi bir makale var

onların argümanları genellikle hevesle değerlendirilmesini de C işlevlerin veya diğer diller gibi çalışır.

0

Sıkı bir işlev, argümanları vücuttan önce değerlendirilen bir işlevdir.

+0

hala anlaşılması zor ... – jackalope

+1

Hayır, argümanları çağrıdan önce değerlendirilen bir işlev değil. Sıkı bir işlev, gayri resmi olarak argümanlarını değerlendiren bir işlevdir. – augustss

+0

@augustss: * koşulsuz (sağ?) –

12

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.