6

OK, es war ein langer Tag und mein Gehirn funktioniert möglicherweise nicht auf Haskell Ebene, aber ich kann nur ein Beispiel aus "Lernen Sie ein Haskell" nicht verstehen.Funktion Anwendung in Haskell

Der Abschnitt Funktion Anwendung mit $ genannt wird, und es ist Beispiel dafür, wie $ definiert werden:

($) :: (a -> b) -> a -> b 
f $ x = f x 

Bisher ist alles klar. Ich verstehe alle Beispiele in dem Abschnitt, mit Ausnahme des zuletzt:

ghci> map ($ 3) [(4+), (10*), (^2), sqrt] 
[7.0,30.0,9.0,1.7320508075688772] 

Hier stellen wir ($ 3) über Liste der Funktionen der Karte und das Ergebnis der Anwendung dieser Funktionen zu 3 bekommen. Aber wie ist das möglich?

Vom ersten Codeausschnitt ist es klar, dass das erste Argument eine Funktion ist, können wir auch schreiben:

*Main> ($) sqrt 4 
2.0 

Jetzt ($ 3) eine partielle Anwendung der Funktion ist $, aber 3 geht auf Funktion Position! Also 3 soll eine Funktion sein oder was?

Es gibt ein anderes Geheimnis: Was zum Teufel ist (4+)? Ich weiß, dass (+4) ist eine teilweise Anwendung der Funktion +, so (4+) sollte teilweise Anwendung der Funktion 4 sein? Unsinn. Was für ein Trick funktioniert hier?

+0

mögliches Duplikat von [Teilanwendung mit Infix-Funktionen] (http://stackoverflow.com/questions/10131300/partical-application-with-infix-functions) – Lambdageek

Antwort

12

($ 3) und (+ 4) sind nicht Teil-Anwendungen reduzieren - sie Operator Abschnitte sind. Eine Teilanwendung würde wie (($) 3) oder ((+) 4) aussehen.

Ein Bedienungsabschnitt des Formulars (? x) (wobei ? steht für eine beliebige Infixoperator), um den rechten Operanden des Operators bindet, das heißt, es zu \y -> y ? x entspricht.Ebenso bindet der Operator-Abschnitt (x ?) den linken Operanden und ist somit äquivalent zur partiellen Anwendung.

6

Ich denke, was Sie stolpert ist Operator Abschnitte. Damit können Sie einen Operator teilweise mit einem seiner Argumente anwenden, sodass Sie die Operatoren (+4) und (4+) haben können, wobei 4 das zweite, dann das erste Argument zu + ist. Ein eindeutigeres Beispiel könnte ("Hello" ++) gegenüber (++ "world") sein, wobei der erstere "Hello" auf die Vorderseite eines Strings vorlegt, während der letztere "world" an das Ende eines Strings anhängt.

Dies steht im Gegensatz zur Verwendung von Operatoren in Präfix Form mit nur Parens um ihn herum. In dieser Form sind die folgende äquivalent:

> let join = (++) 
> join "Hello, " "world" 
"Hello, world" 
> (++) "Hello, " "world" 
"Hello, world" 

In prefix Form behandeln Sie den Bediener als eine normale Funktion und es nimmt dann sein erstes zweites Argument, um. In Operatorabschnitten ist es wichtig, auf welcher Seite des Operators das Argument steht.


So in Ihrem Beispiel haben Sie die partielle Anwendung von ($ 3), können Sie es als

map ($ 3) [(4+), (10*), (^2), sqrt] 
[($ 3) (4+), ($ 3) (10 *), ($ 3) (^ 2), ($ 3) sqrt] 
[4 + 3, 10 * 3, 3^2, sqrt 3] 
[7.0, 30.0, 9.0, 1.7320508075688772] 
+0

"Sie behandeln den Operator als eine normale Funktion", dachte ich diese "Operatoren" sind * normale Funktionen in Haskell. – Mark

+1

@Mark sind sie in jeder Hinsicht anders als ihre Syntax für die Anwendung. Sie sind standardmäßig Infix, während eine Nicht-Operator-Funktion standardmäßig das Präfix ist. Wenn ich normale Funktion sage, meine ich eine Präfix-Funktion. – bheklilr

4

Sie werden mit Abschnitten verwirrt. Ein guter Weg, um das Konzept des Abschnitts spielt mit einem Beispiel zu begreifen:

(<^>) :: Int -> Float -> Int 
a <^> b = a 

Die obige Funktion ist eine unnütze Funktion, die unabhängig von den ersten Parametern gibt, was den zweiten Parameter ist. Aber es akzeptiert Int und dann Float als Eingabe.

Nun, da der Abschnitte können Sie mit einem ihrer Argumente gelten:

λ> let a = (3 <^>) 
λ> :t a 
a :: Float -> Int 
λ> let b = (<^> 3.0) 
λ> :t b 
b :: Int -> Int 

Sehen Sie, wie die Art der a und b unterschiedlich sind wegen Abschnitte.