SORU
21 HAZİRAN 2010, PAZARTESİ


sonsuz listeleri ile foldr davranış foldl karşı

this question myAny işlev kodu foldr kullanır. Yüklem tatmin olduğunda, sonsuz bir liste işlemeyi durdurur.

Ben foldl kullanarak yeniden yazdı:

myAny :: (a -> Bool) -> [a] -> Bool
myAny p list = foldl step False list
   where
      step acc item = p item || acc

(Adım işlevi için argümanlar doğru tersine unutmayın.)

Ancak, artık sonsuz listeleri işlemeyi durdurur.

İşlevin yürütme izleme Apocalisp's answer gibi çalıştım:

myAny even [1..]
foldl step False [1..]
step (foldl step False [2..]) 1
even 1 || (foldl step False [2..])
False  || (foldl step False [2..])
foldl step False [2..]
step (foldl step False [3..]) 2
even 2 || (foldl step False [3..])
True   || (foldl step False [3..])
True

Ancak, bu işlevin davranışı değil. Bu nasıl yanlış?

CEVAP
21 HAZİRAN 2010, PAZARTESİ


foldler farklı nasıl kafa karışıklığı sık görülen bir kaynak gibi görünüyor, burada daha genel bir bakış:

N listesi 6* *bazı işlevi ile [x1, x2, x3, x4 ... xn ] değerleri dikkate katlama ve tohum z.

foldl:

  • Sola ilişkilendirilebilir: f ( ... (f (f (f (f z x1) x2) x3) x4) ...) xn
  • Kuyruk özyinelemeli: Bu liste aracılığıyla, daha sonra değer üreten dolaşır
  • TembelHiçbir şey sonucu ihtiyaç duyduğu kadar değerlendirilir
  • Geriye doğru: foldl (flip (:)) [] bir listeyi tersine çevirir.

foldr

  • Sağ ilişkilendirilebilir: 12**
  • Kavga özyinelemeli: Her tekrarında bir sonraki değer ve katlama sonuç listesi geri kalanı için f geçerlidir.
  • TembelHiçbir şey sonucu ihtiyaç duyduğu kadar değerlendirilir
  • İletir: foldr (:) [] değişmeden bir listesini verir.

foldl. Çünkü insanlar bazen geziler biraz ince bir nokta var: ^strong>geriye doğruf her uygulama için eklenirdışarıdaçünkü sonucu;tembelhiçbir şey kadar değerlendirilmesi sonucu gereklidir. Bu sonuç herhangi bir bölümünü hesaplamak için, ilk yineler Haskell anlamına gelirtüm listesiiç içe fonksiyon uygulamaları bir ifade oluşturarak, değerlendiriren dıştakifonksiyon, gerektiğinde kendi bağımsız değerlendirme. Eğer f Her zaman ilk argüman kullanıyorsa, bu Haskell her şekilde en içteki vadede aşağı recurse, geriye doğru f her uygulama bilgi işlem iş o zaman.

Bu kuyruk özyineleme en işlevsel programcılar bildiği ve sevdiği belli ki verimli bir feryat!

foldl tüm sonuç bir şey ifade değerlendirmeden önce,. inşa çünkü teknik olarak kuyruk özyinelemeli olmasına karşın aslında ^strong>foldl yığın taşmasına neden olabilir!

Diğer taraftan, foldr düşünün. Çalıştığı için de tembel amailetir, f Her uygulama için ekleniriçindesonuç. Yani, sonuç hesaplamak için, yapıları bir Haskelltekfonksiyon uygulama, ikinci bağımsız değişken olan katlanmış listenin geri kalanı. Eğer f ikinci argüman, veri kurucu--tembel, örneğin eğer bir sonucu olacaktıraşamalı tembelihtiyacı olan kısmının değerlendirildiğinde kat edilen her adımda yalnızca hesaplanmış.

Peki biz neden foldr bazen çalışıyor sonsuz listeleri foldl bilmiyor: eski olabilir tembel dönüştürmek sonsuz bir liste halinde başka bir tembel sonsuz veri yapısı, oysa ikincisi incelemek gerekir tüm listesi oluşturmak için herhangi bir sonuç. Diğer taraftan, foldr ile bir işlev ihtiyacı iki tartışmada da derhal gibi ( ) works (ya da daha doğrusu, çalışmıyor) gibi foldl bina büyük bir ifade önce değerlendirmek.

Dikkat edilmesi gereken iki önemli noktaları bunlar:

  • foldr başka bir tembel özyinelemeli veri yapısı dönüştürebilirsiniz.
  • Aksi, tembel kıvrım yığını büyük ya da sonsuz listelerinde taşması ile kilitlenmesine.

foldr foldl her şeyi, artı daha yapabilir gibi görünüyor fark etmişsinizdir. Bu doğru! Aslındafoldl işe yaramaz neredeyse!

Ama eğer (ama sınırsız değil) geniş bir liste üzerinde katlayarak olmayan tembel bir sonucu elde etmek istersek ne olacak? Bunun için, bir istiyoruzsıkı katlayın41**:,

foldl'

  • Sola ilişkilendirilebilir: 33**
  • Kuyruk özyinelemeli: Bu liste aracılığıyla, daha sonra değer üreten dolaşır
  • KatıHer fonksiyonu uygulama yol boyunca değerlendirilir
  • Geriye doğru: foldl' (flip (:)) [] bir listeyi tersine çevirir.

foldl' çünkükatıHaskell olacak sonuç hesaplamak içindeğerlendirinSol argüman izin vermek yerine, her adımda, f büyük, unevaluated bir ifade birikir. Bu bize istediğimiz her zamanki gibi, verimli kuyruk özyineleme verir! Diğer bir deyişle:

  • foldl' büyük listeleri verimli bir şekilde katlayın.
  • foldl' sonsuz bir döngü (yığın taşmasına neden değil) sonsuz bir liste asılı olacak.

Haskell wiki 42**, de vardır.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • fast2hell

    fast2hell

    16 AĞUSTOS 2006
  • Peter Sharp

    Peter Sharp

    11 ŞUBAT 2013
  • tseyina

    tseyina

    2 AĞUSTOS 2006