2016-07-03 5 views
1

Ich verstehe die Definitionen von foldl, foldr, aber ich habe Probleme mit Funktionen durch sie definiert.Funktionen definieren mit foldl foldr

Zum Beispiel Karte mit foldr:

map f []  = [] 
map f l = foldr (\x xs -> f x : xs) [] l 

Ich verstehe nicht, die (\x xs -> f x : xs). Es ist die Kartenfunktion, die foldr nimmt? Aber sollte es nicht (\x xs -> f x : f xs) sein, weil map f (x:xs) = f x : map f xs?

Beispiel mit foldl:

concat (x:xs) = x ++ concat xs 

concat' xs = foldl (++) [] xs 
concat'' xs = foldl (\ys y -> ys ++ y) [] xs 

Natürlich ich (++) verstehen, aber was ist die Logik hinter (\ys y -> ys ++ y)? Ist es ys = [] und y = xs? Also die Funktion dauert [] als ys und y ist das erste Element von xs und concases die [] mit der y? Konkretes Beispiel:

concat'' [1,2,3] = foldl (\ys y -> ys ++ y) [] [1,2,3] 
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [] [1]) [2,3] 
=> foldl (\ys y -> ys ++ y) [1] [2,3] 
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1] [2]) [3] 
=> foldl (\ys y -> ys ++ y) [1,2] [3] 
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1,2] [3]) [] 
=> foldl (\ys y -> ys ++ y) [1,2,3] [] 
=> [1,2,3] 

Eine andere Sache: concat dauert nur 1 Liste xs, also wenn ich 2 Listen verketten wollen?

concat (x:xs) ys = x ++ concat xs ys 
concat [1,2,3] [4,5,6] with foldl? 

Rückseite:

reverse (x:xs) = reverse xs ++ [x] 

reverse' l = foldl (\xs x -> [x] : xs) [] l 
reverse'' l = foldr (\x xs -> xs ++ [x]) [] l 

Die foldr intuitiv klar ist (mit den Fragen von oben), aber was in foldl (\xs x -> [x] : xs) hinter der umgekehrten Reihenfolge ist? Diese foldl (\x xs -> xs ++ [x]) [] l wäre falsch, oder?

Vielen Dank!

+1

das ist ein paar Fragen - für die erste Beobachtung, dass die 'xs' die re * wurde * mit 'f' gemappt (siehe die Definition von' foldr', um zu sehen, warum) (auch 'fxs' wäre nicht gut typisiert, wie du' f :: a -> b' und im gleiche Zeit 'f :: [a] -> b'', also müssten Sie' a ~ [a] ') identifizieren – Carsten

+0

Beachte, dass' foldr fz [x1, x2, x3] = f x1 (f x2 (f x3 z)) 'so wurde das' xs' bereits durch 'f' abgebildet. – Bakuriu

+0

für die zweite: nur beachten Sie, dass 'foldl 'wird * loop * durch' xs' von links (wieder auf die Definition) – Carsten

Antwort

2

Der Code

foldr (\x xs -> ...) end list 

, grob gelesen werden kann, wie folgt

  • die ganzen scannen list
  • wenn es leer ist, einfach zurückgeben Ende end
  • sonst:
    • lassen x das Element zur Hand
    • lassen xs der Rest der Liste sein, nach
    • verarbeitet worden gelten die ... Betrieb

Der Teil ist entscheidend hervorgehoben. xs ist nicht der Rest der Liste, aber das Ergebnis des "rekursiven Aufrufs" darauf.

Tatsächlich ist xs ein schlechter Name dafür. Im allgemeinen Fall ist es nicht einmal eine Liste! Z.B.man würde nie (dummes Beispiel)

foldr (\x xs -> x + xs) 0 [1..100] -- sum 1..100 

schreiben, sondern eher so etwas wie

foldr (\x partialSum -> x + partialSum) 0 [1..100] -- sum 1..100 

bevorzugen (Eigentlich würde man nicht foldr Summe verwenden, aber lassen wir das beiseite.)

So, lesen Sie es einfach so:

map f l = foldr (\x mappedTail -> f x : mappedTail) [] l 
+0

Danke! Ich denke ich verstehe foldr. Karte mit Foldl wäre so? 'map f l = foldl (\ x xs -> x: f xs) [] l' Also ist' x' der zugeordnete Teil und 'xs' ist abgebildet? – user22709

+0

@ user22709 Moralisch ja, aber beachte, dass in diesem Fall 'x' eine (gemappte) Liste ist und' xs' ein Element ist, also sollte es 'foldl (\ xxs -> x ++ [f xs]) sein [] ] liste' – chi

+0

Danke! Hast du einen Vorschlag für eine elegantere Schreibweise, weil xs normalerweise der Rest der Liste ist, was hier nicht der Fall ist ... – user22709

Verwandte Themen