2017-09-20 5 views
3

Angenommen b eine Liste von Strings ist und prüfen,Funktion Zusammensetzung in Haskell Beispiel

map (map (\a -> ((head a), (length a))) . group . sort) (transpose b)

Ich weiß, was jede einzelne Funktion oben tut, aber ich habe Probleme zu sehen, wie das Ergebnis zusammengebaut wird. Wie würde ich herausfinden, in welcher Reihenfolge die Funktionen in dieser Zeile laufen, mit welchen Parametern?

Insbesondere scheint ich zu verstehen, dass (map (\a -> ((head a), (length a))) . group . sort) ist der erste Parameter für die äußere Karte und (transpose b) ist der zweite Parameter der äußeren Karte.

Aber welche sind die Parameter für die innere Karte? Die innere Karte scheint nur einen Parameter zu haben: (\a -> ((head a), (length a))) . group . sort). Wo ist der zweite Parameter (die Liste, auf die elementweise die Funktion im ersten Parameter angewendet werden soll)?

+0

Mögliches Duplikat von [Haskell - Probleme beim Verständnis eines kleinen Codes] (https://stackoverflow.com/questions/46131310/haskell-having-trouble-understanding-a-small-bit-of-code) –

Antwort

1

Was Sie bemerkt haben, heißt currying und es ist einer von vielen großartigen (oder vielleicht auch nicht) Aspekten der Haskell-Funktionen.Dies ist Ihr Code:

map (\a -> ((head a), (length a))) :: [[a]] -> [(a, Int)] 

Wir tun dies, indem Sie diese

:t map (\a -> ((head a), (length a))) 

in GHCI:

map (map (\a -> ((head a), (length a))) . group . sort) (transpose b) 

der den Typ des ersten map Lassen Sie überprüfen.

So wissen wir, dass es eine Funktion ist. Es nimmt ein Element vom Typ [[a]] und gibt [(a, Int)] zurück. Geben Sie den Typ der Kartenfunktion ist

map :: (a -> b) -> [a] -> [b] 

Das ist völlig in Ordnung. Wir haben map gegeben, es ist das erste Argument, jetzt, alles was es braucht ist eine richtige Liste. Was gerade mit der Karte passiert ist, heißt currying.

Nun wollen wir sehen, haben wir unsere map „verbunden“ sort und group durch die (.) Funktion.

(.) :: (b -> c) -> (a -> b) -> a -> c 

Lassen Sie uns nun ein wenig ändern Sie Ihr Stück Code, damit wir besser sehen, was mit der Zusammensetzung Funktion vor sich geht.

map (\a -> ((head a), (length a))) . (group . sort) 

ich getrennt nur group und sort mit einigen Klammern. Aber jetzt sehen wir klar, welche Elemente als Argumente der äußeren (.) fungieren.

Wir haben die Karte in Frage, und eine andere Funktion, die aus der anderen Zusammensetzung ergibt. Auch hier haben wir die in Aktion anzubiedern, wenn wir das letzte Argument auslassen:

map (\a -> ((head a), (length a))) . (group . sort) 
:: Ord a => [a] -> [(a, Int)] 

Schließlich wird die äußere map die Funktion nimmt von oben und eine Liste (transpose b).

1

Es wird implizit angegeben. Wenn Sie schreiben:

map (\a -> ((head a), (length a))) . group . sort 

dies tatsächlich kurz ist:

\b -> (map (\a -> ((head a), (length a))) . group . sort) b 

was äquivalent ist:

\b -> map (\a -> ((head a), (length a))) $ group $ sort b 

oder:

\b -> map (\a -> ((head a), (length a))) (group (sort b)) 

Der (.) :: (b -> c) -> (a -> b) -> a -> c Operator, so komponiert zwei Funktionen zusammen ther in einer Art Pipeline:

(.) f g x = f (g x) 

Da wir hier drei Funktionen, die durch Punkte getrennt schreiben:

map (\a -> ((head a), (length a))) . group . sort 
-- \_________________ ______________/ \_ _/ \_/
--     v     v  v 
--     f     g  h 

wir eine Art Pipeline definiert haben, in dem ein Element zuerst durch h verarbeitet wird, dann ist das Ergebnis wird durch g verarbeitet, und schließlich wird das Ergebnis davon durch f verarbeitet.

1

Der Punkt ist selbst eine Funktion, die wie folgt definiert:

(f . g) x = f (g x) 

Lassen Sie sich diese Gleichung auf die äußeree Karte im ersten Argumente verwenden:

map (\a -> (head a, length a)) . group . sort 
= { definition of (.), with map (\a -> ...) as f and group . sort as g } 
\x -> map (\a -> (head a, length a)) ((group . sort) x) 

So map (\a -> ...) . group . sort ist eine Funktion, die, Wenn auf das Argument x angewendet, liefert (group . sort) x als Argument an map (\a -> ...).