2017-09-14 53 views
8

üzerinde çalışır. LYAH'da, buna benzeyen bir kod parçası vardır.Foldable.foldl, Num a => a

data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show, Read, Eq) 

instance F.Foldable Tree where 
    foldMap f Empty = mempty 
    foldMap f (Node x l r) = F.foldMap f l `mappend` 
          f x   `mappend` 
          F.foldMap f r 

ghci> F.foldl (+) 0 testTree 
42 
ghci> F.foldl (*) 1 testTree 
64800 

olarak bildiğim kadarıyla, foldMap tip foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> m ait olmakla Num a => a kendisi değil tip Monoid ait, yani Foldable.foldl aslında burada çalışıyor mu merak ediyorum? Ve foldMap dahili olarak Foldable.foldl tarafından çağrıldığı için Monoid'un türü nedir?

+0

Merhaba @WillemVanOnsem, yardımın için teşekkürler. Bu tam olarak kafam karıştı, 'mempty = 1' den bahsettin, o zaman buradaki "mempty" nin türü nedir? Bunu tam olarak anlayamıyorum çünkü 'Sum' ve' Product''nın aksine Int', “Monoid' AFAIK” tipinde değil. Bunun hakkında biraz daha açıklayabilir misiniz? teşekkürler –

+0

Hmm, anlıyorum, Haskell’e yeni geliyorum, sanırım eksik olduğum kısım bu. Çok teşekkürler :) –

+1

Bu endo hilesinin, kesinlikle yeni başlayan materyal olmadığına dikkat edin. Belki de 'katlama' ('x'> 'x]) 'i kullanarak katlanabilir herhangi bir dosyayı düz bir listeye dönüştüren bir' katlama 'uygulaması yazmak daha kolaydır, böylece tek-basitçe' [a]' dır ve Listede foldl'. Daha az verimli, ama muhtemelen daha kolay anlaşılır. Bu iyi bir egzersiz için yapabilirdi :) – chi

cevap

9

(a -> b -> b) -> b -> t a -> b türüne sahip olan foldr öğelerini dikkate alırsanız, bunu anlamak biraz daha kolaydır. 'Cebir' işlevi, a -> (b -> b) olarak görüntüleyebileceğiniz a -> b -> b türüne sahiptir; yani: a giriş olarak alır ve çıktı olarak b -> b değerini döndürür.

Şimdi, b -> b da monoid bir Endomorfizma, ve Data.Monoid bir tür Endo a tanımlar (ya da burada, bu Endo b olması belki gerektiğini), olan, gerçekten de, bir Monoid.

foldr :: (a -> b -> b) -> b -> t a -> b 
foldr f z t = appEndo (foldMap (Endo #. f) t) z 

foldl temelde sadece aynı hile yapmak için etrafında argümanlar çevirir:

foldr basitçe foldMap çağırmak için içten Endo kullanır

foldl :: (b -> a -> b) -> b -> t a -> b 
foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z 

Açık olmak gerekirse, ben tam anlamıyla kopyalanan bu Haskell kaynağından iki fonksiyon uygulaması. documentation of Data.Foldable'a giderseniz, kaynağı görüntülemek için çeşitli bağlantılar vardır. Ben de öyle yaptım.

+0

Gerçekten kaynak kodun bir kısmını buldum, ama Haskell için yeni olduğum gibi 'Endo' rolünü anlayamadım, bu konuda daha fazla okuyacak. Çok teşekkür ederim :) –

İlgili konular