2013-02-02 28 views
5

Şimdi, dümdüz noktasına gelin.harita. foldr fonksiyon kompozisyonu - Haskell

:t (map.foldr) 
(map.foldr) :: (a1 -> a -> a) -> [a] -> [[a1] -> a] 

[[a1] -> a] nedir? Gerçekten bu kompozisyon anlamaya çalışıyorum, bu yüzden bu yapıyordu:

-- map.foldr 

    map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a] 

    map :: (a1 -> b1) -> [a1] -> [b1] 
    (.) :: (y -> w) -> (x -> y) -> x -> w 
    foldr :: (a -> b -> b) -> b -> [a] -> b 

    y = (a1 -> b1)  w = ([a1] -> [b1]) 
    x = (a -> b -> b) y = (b -> [a] -> b) 

    y = (a1 -> b1) 
    y = (b -> [a] -> b) 
_________________________ 

Ne bu noktada olur? Teşekkür ederim!

+1

'foldr' tipi yanlış,' (a -> b -> b) -> b -> [a] -> b' olmalıdır. –

cevap

14

bu ne hatırlamak iyidir Bu soruyu cevaplamak için foldr ve map yapar.

1 : 2 : 3 : [] 

hareket:

ikisinin daha karmaşık çok conses (:) ve bir terminal boş liste bir zincir olup, foldr olan

--    list to be folded 
--        v 
foldr :: (a -> b -> b) -> b -> [a] -> b 
--   ^  ^
--folding function  terminal value 

katlanabilir listeyi tip olan foldr, : ve [] yapıcılarını sırasıyla katlama işlevi ve uçbirim değeriyle değiştirmektir:

foldr (+) 0 (1 : 2 : 3 : []) == 1 + 2 + 3 + 0 

map işlevi basittir.

map :: (a -> b) -> [a] -> [b] 
--  ^  ^
-- function   list 

Ancak, aynı zamanda bir işlev alarak ve onu kaldırma olarak düşünebilirsiniz edebilirsiniz: bunun düşünce bir yolu listesinin her argüman fonksiyonu bir işlev ve bir liste alarak ve uygulayarak gibidir

map :: (a -> b) -> ([a] -> [b]) 
--  ^   ^
-- function    function on lists 

o map . foldr bu iki işlevi oluşturmak için ne anlama gelir: bunun yerine listelerde davranan bir işlev olabilir mi?bu sadece fonksiyonları birbiri ardına uygulayarak unutmayın - Özellikle

(map . foldr) f == map (foldr f) 

Uygulamak yana foldr ilk bir fonksiyona f :: a -> b -> b uygulayarak olması ve başka bir işlev geri almak:

foldr f :: b -> [a] -> b 
--  ^ ^
--terminal val list to be folded 

map (foldr f) :: [b] -> [[a] -> b] 
--    ^  ^
--list of terminal vals  functions that fold lists 
Bu tip tuhaf görünüyor

, met:

Şimdi listelerde hareket etme fonksiyonunu kaldırır map, uygulamak t geçerli. Şimdi, tek bir terminal değeri yerine, terminal değerlerinin bir listesini verirsiniz ve size sağladığınız her bir terminal değeri için bir katlama işlevi listesi alırsınız.


daha anlaşılır biz yukarıdaki denklemde içine yerine, biz

(map . foldr) (+) :: Num a => [a] -> [[a] -> a] 
--       ^  ^
--   list of terminal vals   functions that fold lists 

ise olsun

(+) :: Num a => a -> a -> a 

tip vardır, belirli bir fonksiyonu (+), bakmak olabilir yapmak için Şimdi [0, 1, 2] numaralı listeye uygularız, üç fonksiyonun bir listesini alırız:

(map . foldr) (+) [0,1,2] :: Num a => [[a] -> a] 

Listedeki tüm işlevleri belirli bir bağımsız değişkene uygulamak için map ($x) deyimini kullanabiliriz. Sayıların bir listesi olmalı ve ben [3,4,5]'u seçeceğim. dikkatle takip:

> map ($[3,4,5]) ((map.foldr) (+) [0,1,2]) 
[12, 13, 14] 

[3,4,5] katlama işlevi olarak (+) kullanılarak üç kez katlanmış listesini ve farklı bir uç değer ile, her zaman: Terminal değeri 0 olduğunda

3 + 4 + 5 + 0 == 12 
3 + 4 + 5 + 1 == 13 
3 + 4 + 5 + 2 == 14 

, basitçe elde Değerlerin toplamı: 3 + 4 + 5 == 12. Terminal değeri 1 olduğunda, değerlerin toplamından (13) bir tane daha aldık ve terminal değeri 2 olduğunda, değerlerin toplamından (14) iki tane daha aldık.

+0

"map ($ x)" deyimiyle ilgili daha fazla bilgiyi nerede bulabilirim? Anlayamıyorum. Oh, ve cevabınız için teşekkürler, gerçekten yararlı :) – dehq

+1

'$ 'islemcisi' f $ x = f x' ile tanimlanmistir, yani fonksiyonunu solunda soldaki argümana uygular. Bu kesinlikle gereksizdir, ancak iki yolla yardımcı olur: 1. $ 'operatörünün en düşük önceliği vardır ve en sağdadır (en yüksek önceliğe ve iş ortaklarına sahip olan işlev uygulamasının aksine), böylece bunun yerine" $ gb $ hc "yazabilirsiniz. fa (gb (hc)) ', ve 2. bunu bir bölümde kullanabilirsiniz, böylece' \ f -> fa' yerine '($ f)' yazabilirsiniz. 'Map ($ x)' kodu bu nedenle "map (\ a -> x a)" ile aynı anlama gelir. –

1
map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a] 

map :: (a1 -> b1) -> [a1] -> [b1] 
(.) :: (y -> w) -> (x -> y) -> x -> w 
foldr :: (a -> b -> b) -> b -> [a] -> b 

-- if you substitute: x = (a -> b -> b) y = (b -> [a] -> b) 
-- then you get for map :: (b -> ([a] -> b)) -> [b] -> [[a] -> b] 
-- so if composition operator applied: 
map . foldr :: (a -> b -> b) -> [b] -> [[a] -> b] 
2

kaldığınız yerden, y iki tanımları eşit olmalıdır devam etmek : tanımı yazısı ikisini temin edilmiştir

a1 = b 
b1 = [a] -> b 

:

y = (a1 -> b1) = (b -> [a] -> b) 
       = (b -> ([a] -> b)) 

yüzden sonucuna varabiliriz işlev argümanları, sonuçta elde edilen tür sadece:

x -> w 

Ama biz biliyoruz:

x = a -> b -> b 
w = [a1] -> [b1] = [b] -> [[a] -> b] 

Yani, sonuç türüdür: için uyumlu olan

(x -> w) = ((a -> b -> b) -> ([b] -> [[a] -> b])) 
     = (a -> b -> b) -> [b] -> [[a] -> b] 

:

(a1 -> a -> a) -> [a] -> [[a1] -> a]