2009-09-25 9 views
21

Ich lese this Tutorial auf Haskell. Sie definieren Zusammensetzung Funktion wie die folgenden:Haskell Funktionszusammensetzung

(.)      :: (b->c) -> (a->b) -> (a->c) 
f . g     = \ x -> f (g x) 

keine Beispiele zur Verfügung gestellt wurden, die ich glauben würde, mich erleuchten, was hier definiert wird.

Kann jemand ein einfaches Beispiel (mit Erklärung) geben, wie die Funktionszusammensetzung verwendet wird?

Antwort

38

Funktionszusammensetzung ist eine Möglichkeit, zwei Funktionen zu einer einzigen Funktion zusammenzusetzen. Hier ein Beispiel:

Sagen Sie diese Funktionen haben:

even :: Int -> Bool 
not :: Bool -> Bool 

und Sie möchten Ihre eigene myOdd :: Int -> Bool Funktion unter Verwendung der beiden oben definieren.

Der offensichtliche Weg, dies zu tun, ist die folgende:

myOdd :: Int -> Bool 
myOdd x = not (even x) 

Aber diese kurz und bündig Funktion Zusammensetzung verwendet getan werden kann:

myOdd :: Int -> Bool 
myOdd = not . even 

Die myOdd Funktionen verhalten sich genau das gleiche, aber die zweite man wird geschaffen, indem man zwei Funktionen miteinander "klebt".

Ein Szenario, in dem dies besonders nützlich ist, ist das Entfernen eines expliziten Lambda. Z. B: für Fehler

map (not . even) [1..9] 

Ein bisschen kürzer, weniger Raum:

map (\x -> not (even x)) [1..9] 

kann neu geschrieben werden.

+0

Wie kommt es, dass Sie den Eingabeparameter in der Definition nicht anzeigen müssen? Zum Beispiel. Wieso schreibst du nicht 'myOdd x = nicht. sogar x'? – unclerojelio

+2

@unclerojelio Es heißt punktfreier Stil. Anstatt "myOdd" in Bezug auf das Ergebnis für ein gegebenes Argument zu definieren ("Given' x', 'myOdd' gibt den gleichen Wert wie' (not. Even) x' "zurück), wird es in Bezug auf was es tatsächlich definiert is ("' myOdd' ist die Funktion, die entsteht, wenn 'not' aus' even' besteht). – chepner

13

Die Zusammensetzung vonf und g ist eine Funktion, die ersten g sein Argument gilt, dann f an den von g zurückgegebene Wert. Es gibt dann den Rückgabewert f zurück.

kann diese Identität aufschlussreich sein:

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

Wenn Sie einen Java/C Hintergrund haben, um dieses Beispiel betrachten:

int f(int x); 
int g(int x); 
int theComposition(int x) { return f(g(x)); } 
+0

+1 für Äquivalenz – outis

4

Vom HaskellWiki page on function composition:

desort = (reverse . sort) 

Jetzt desort ist eine Funktion, die eine Liste in umgekehrter Reihenfolge sortiert. Im Grunde desort füttert es Argumente in sort, und füttert dann den Rückgabewert von sort in reverse, gibt das zurück. Also sortiert er es und kehrt dann die sortierte Liste um.

7

Dieses Beispiel ist gekünstelt, aber angenommen, wir haben

sqr x = x * x 
inc x = x + 1 

und wir wollen, eine Funktion schreiben, die x berechnet^2 + 1. Wir können

xSquaredPlusOne = inc . sqr 

(was bedeutet,

xSquaredPlusOne x = (inc . sqr) x 

die

bedeutet
xSquaredPlusOne x = inc(sqr x) 

da f = inc und g = sqr) schreiben.

26

Fun Seitennotiz. Funktionszusammensetzung ist das Äquivalent eines Syllogismus in der Logik:

Alle Männer sind sterblich. Sokrates ist ein Mann. Daher ist Sokrates sterblich.

A syllogism komponiert zwei wesentlichen Auswirkungen in einem:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal) 

Daher ...

(b -> c) -> (a -> b) -> (a -> c) 

..., die die Art der . Funktion ist.

3

Funktionszusammensetzung ist eine Möglichkeit, zwei oder mehr Funktionen miteinander zu verketten. Es wird oft mit Rohrpaspel verglichen. Zum Beispiel in einem Unix-Shell-Stil, können Sie so etwas wie

cat foo.txt | sort -n | less 

Dies läuft cat, seine Ausgabe an sort und führt die Ausgabe von der zu less schreiben.

Genau dies ist wie der Haskell $ Operator. Sie könnten etwas wie

schreiben
sum $ sort $ filter (> 0) $ my_list 

Beachten Sie, dass im Gegensatz zum Shell-Beispiel von rechts nach links liest. Also wir beginnen mit my_list als Eingabe, dann laufen wir filter darüber, dann wir sort es, und dann berechnen wir die sum davon.

Der Funktionszusammensetzungsoperator . tut etwas ähnliches. Das obige Beispiel erzeugt eine Nummer; das folgende Beispiel erzeugt eine Funktion:

sum . sort . filter (> 0) 

Beachten Sie, dass wir eigentlich nicht eine Liste in diesem Feed. Stattdessen haben wir eine neue Funktion erstellt und können dieser Funktion mehrere verschiedene Listen hinzufügen.Zum Beispiel könnten Sie diese Funktion nennen:

my_function = sum . sort . filter (> 0) 

Oder Sie könnten es als Argument an eine andere Funktion übergeben:

map (sum . sort . filter (> 0)) my_lists 

Sie können es im Grunde überall dort verwenden, dass Sie eine andere Art von Funktion nutzen zu können . Es ist nur eine schnelle und lesbare Art zu sagen: "Ich möchte diese Funktionen miteinander verketten".