5 Stimmen

Verwirrung über Funktionskomposition in Haskell

Betrachten Sie die folgende Funktionsdefinition in ghci.

let myF = sin . cos . sum 

wobei . für die Komposition von zwei Funktionen steht (rechts-assoziativ). Dies kann ich nennen

myF [3.14, 3.14]

und ich erhalte das gewünschte Ergebnis. Offensichtlich wird die Liste [3.14, 3.14] an die Funktion 'sum' übergeben und deren 'Ergebnis' an cos und so weiter und so fort. Wenn ich dies jedoch im Interpreter mache

let myF y = sin . cos . sum y 

o

let myF y = sin . cos (sum y) 

dann stoße ich auf Probleme. Wenn ich dies wie folgt ändere, erhalte ich das gewünschte Ergebnis.

let myF y = sin . cos $ sum y 

o

let myF y = sin . cos . sum $ y 

Der Typ von (.) legt nahe, dass es kein Problem mit der folgenden Form geben sollte, da 'sum y' auch eine Funktion ist (nicht wahr? Schließlich ist in Haskell alles eine Funktion?)

let myF y = sin . cos . sum y -- this should work?

Was noch interessanter ist, ist die Tatsache, dass ich es mit zwei (oder vielen) Argumenten zum Laufen bringen kann (denken Sie an die Übergabe der Liste [3.14, 3.14] als zwei Argumente x und y), ich muss folgendes schreiben

let (myF x) y = (sin . cos . (+ x)) y 
myF 3.14 3.14 -- it works! 
let myF = sin . cos . (+) 
myF 3.14 3.14 -- -- Doesn't work!

Es gibt eine Diskussion auf HaskellWiki über diese Form, die sie 'PointFree' Form nennen http://www.haskell.org/haskellwiki/Pointfree . Wenn ich diesen Artikel lese, vermute ich, dass sich diese Form von der Komposition zweier Lambda-Ausdrücke unterscheidet. Ich bin verwirrt, wenn ich versuche, eine Trennlinie zwischen diesen beiden Formen zu ziehen.

10voto

Mihai Maruseac Punkte 20459

Schauen wir uns die Typen . Für sin y cos haben wir:

cos, sin :: Floating a => a -> a

Für sum :

sum :: Num a => [a] -> a

Jetzt, sum y verwandelt das in eine

sum y :: Num a => a

was ein Wert und keine Funktion ist (man könnte es eine Funktion ohne Argumente nennen, aber das ist sehr schwierig und man muss auch den Namen () -> a Funktionen - Es gab irgendwo eine Diskussion darüber, aber ich kann den Link nicht mehr finden. - Conal sprach darüber).

Wie auch immer, der Versuch cos . sum y wird nicht funktionieren, weil . erwartet, dass beide Seiten Typen haben a -> b y b -> c (Unterschrift ist (b -> c) -> (a -> b) -> (a -> c) ) und sum y kann nicht in diesem Stil geschrieben werden. Deshalb müssen Sie Klammern einfügen oder $ .

Was den punktfreien Stil betrifft, so lautet das einfache Übersetzungsrezept wie folgt:

  • nehmen Sie die Funktion und verschieben Sie das letzte Argument der Funktion an das Ende des Ausdrucks, der durch eine Funktionsanwendung getrennt ist. Zum Beispiel, im Fall von mysum x y = x + y wir haben y am Ende, aber wir können es im Moment nicht entfernen. Stattdessen schreiben wir um in mysum x y = (x +) y es funktioniert.
  • dieses Argument zu beseitigen. In unserem Fall mysum x = (x +)
  • wiederholen, bis Sie keine Argumente mehr haben. Hier mysum = (+)

(Ich habe ein einfaches Beispiel gewählt, für kompliziertere Fälle müssen Sie die flip und andere)

7voto

hammar Punkte 136080

Nein, sum y ist keine Funktion. Es ist eine Zahl, genau wie sum [1, 2, 3] ist. Es ist daher völlig logisch, dass Sie den Funktionskompositionsoperator nicht verwenden können (.) mit ihm.

Nicht alles in Haskell sind Funktionen.

4voto

Dan Burton Punkte 52363

Die obligatorische kryptische Antwort lautet wie folgt: (Raum) bindet fester als .

Die meisten Leerzeichen in Haskell kann man sich als eine sehr hoch-fixe $ (die Funktion "Anwenden"). w x . y z ist im Grunde dasselbe wie (w $ x) . (y $ z)

Wenn Sie zum ersten Mal etwas über $ y . sollten Sie sich auch über Folgendes informieren (Leerzeichen), und stellen Sie sicher, dass Sie verstehen, wie die Semantik der Sprache implizit Dinge in Klammern setzt, die (auf den ersten Blick) nicht intuitiv erscheinen mögen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X