2010-06-26 16 views
30

Ich versuche, etwas über mich selbst über Operator und Funktion Vorrang in Haskell zu verifizieren. Zum Beispiel der folgende CodeHaskell Operator vs Funktion Vorrang

list = map foo $ xs 

als

list = (map foo) $ (xs) 

neu geschrieben werden und wird schließlich sein

list = map foo xs 

Meine Frage früher, warum die erste Formulierung nicht so neu geschrieben werden würde

list = (map foo $) xs 

da die Funktionspriorität immer höher ist als die Operatorpriorität, aber ich denke, dass ich die Antwort gefunden habe: Operatoren dürfen einfach keine Argumente von Funktionen sein (außer natürlich, wenn man sie mit Klammern umgibt). Ist das richtig? Wenn dem so ist, finde ich es merkwürdig, dass es in RWH oder Learn you a Haskell oder irgendeinen anderen Ort, an dem ich gesucht habe, keine Erwähnung dieser Mechanik/Regel gibt. Wenn du also einen Ort kennst, an dem die Regel steht, verlinke bitte darauf.

- bearbeiten: Vielen Dank für Ihre schnellen Antworten. Ich glaube, meine Verwirrung kam dadurch, dass ich dachte, dass ein Operator-Literal irgendwie etwas auswerten würde, das von einer Funktion als Argument konsumiert werden könnte. Es half mir, mich daran zu erinnern, dass ein Infix-Operator mechanisch in eine Präfix-Funktion übersetzt werden kann. Dies trägt zur ersten Formulierung Ausbeuten

($) (map foo) (xs) 

wo es kein Zweifel daran, dass ($) ist die verzehrende Funktion, und da die beiden Formulierungen äquivalent sind, dann ist der $ wörtliche in der ersten Formulierung kann nicht auf der Karte verbraucht werden.

Antwort

20

Sie haben Recht. Diese Regel ist Teil der Haskell-Syntax, die von Haskell Report definiert wird. Beachten Sie insbesondere in Abschnitt 3, Ausdrücke, dass das Argument zur Funktionsanwendung (ein fexp) ein aexp sein muss. Ein aexp erlaubt Operatoren als Teil von Abschnitten und auch innerhalb eines geklammerten Ausdrucks, aber nicht als bloße Operatoren.

In map foo $ xs bedeutet die Haskell-Syntax, dass dies als zwei Ausdrücke analysiert wird, die auf den binären Operator $ angewendet werden. Wie Sepp2k feststellt, ist die Syntax (map foo $) ein linker Abschnitt und hat eine andere Bedeutung.

Ich muss gestehen, ich habe nie viel darüber nachgedacht und musste tatsächlich im Bericht nachsehen, warum Betreiber das Verhalten haben, das sie tun.

8

Operatoren können als Funktionsargumente übergeben werden, wenn Sie sie mit Klammern umgeben (d. H. map foo ($) xs, die tatsächlich als (map foo ($)) xs übergeben würde). Wenn Sie sie jedoch nicht mit Klammern umgeben, haben Sie Recht, dass sie nicht als Argument übergeben (oder Variablen zugewiesen) werden können.

Beachten Sie auch, dass die Syntax (someValue $) (wo $ jeder Betreiber sein könnte) bedeutet eigentlich etwas anderes: es entspricht \x -> someValue $ x, dh es gilt teilweise den Betreiber seinen linken Operanden (die im Falle von $ ein noop natürlich). Ebenso wendet ($ x) den Operator teilweise auf den rechten Operanden an. So würde zu [f x, g x, h x] auswerten.

27

Erstens, Anwendung (Leerzeichen) ist die höchste Priorität "Operator".

Zweitens, in Haskell gibt es wirklich keinen Unterschied zwischen Operatoren und Funktionen, abgesehen davon, dass Operatoren standardmäßig Infix sind, während Funktionen nicht sind. Sie können Funktionen konvertieren mit Backticks

2 `f` x 

und konvertieren Betreiber infix mit Pars Präfix:

(+) 2 3 

Also, Ihre Frage ist ein wenig verwirrt.

nun spezifische Funktionen und Operatoren werden haben Vorrang erklärt, was Sie in GHCi mit finden „: info“:

Prelude> :info ($) 
($) :: (a -> b) -> a -> b -- Defined in GHC.Base 

infixr 0 $ 

class (Eq a, Show a) => Num a where 
    (+) :: a -> a -> a 

infixl 6 + 

Zeigen beide Vorrang und Assoziativität.

+0

Vielen Dank. Nach dem Lesen Ihrer Antwort, wenn Sie sagen, dass meine Frage ein wenig verwirrt ist, nehme ich es zu verstehen, dass meine Erwähnung der "Funktionspräzedenz" falsch ist, und dass Funktionen an sich keinen Vorrang haben, sondern eher als gedacht werden können Argumente für den Anwendungsoperator whitespace. Ist das richtig? Mir ist noch nicht ganz klar, wie Infix-Operatoren dazu passen. Ich habe meine Frage bearbeitet, um zu reflektieren, wie ich am besten darüber nachdenken kann. Ist dieses Verständnis korrekt? – Boris

+0

Nein, nicht ganz. Funktionen und Operatoren sind in Haskell nicht zu unterscheiden. Sie können beide unterschiedliche Prioritätsstufen haben, die vom Benutzer festgelegt werden. –

+3

Ok. Ich versuche immer noch, die allgemeine Regel herauszufinden, die zu list = (map foo) $ (xs) statt list = (map foo $) xs führt - was ich weiß, ist ein Abschnitt. Kann man sagen, dass bei der Entscheidung, welche Argumente zu welchen Funktionen und Operatoren gehören, Funktionen - beginnend von links - alle möglichen Argumente konsumieren, bis sie einen Operator erreichen.Danach konsumieren die Operatoren ihre Argumente entsprechend ihrer Präzedenz und Assoziativität (Das ist irgendwie vage, aber ich hoffe, Sie verstehen es). Tut mir leid, wenn das offensichtlich scheint, aber es war mir nie wirklich klar. – Boris

10

Der Unterschied besteht darin, dass Infixoperatoren zwischen ihren Argumenten gestellt bekommen, so dass diese

list = map foo $ xs 

kann in Präfix Form als

list = ($) (map foo) xs 

, die durch die Definition des $ Operator neu geschrieben werden, ist einfach

list = (map foo) xs 
9

Zusätzlich zu den Informationen, die bereits von anderen Antworten zur Verfügung gestellt wurden, ist zu beachten, dass verschiedene Operatoren unterschiedliche Vorrang vor anderen Operatoren haben können und auch links/rechts oder nicht-assoziativ sein können. Sie finden diese Eigenschaften für die Operatoren Prelude in Haskell 98 Report fixity section.

 
+--------+----------------------+-----------------------+-------------------+ 
| Prec- | Left associative | Non-associative | Right associative | 
| edence |  operators  |  operators  | operators  | 
+--------+----------------------+-----------------------+-------------------+ 
| 9  | !!     |      | .     | 
| 8  |      |      | ^, ^^, **   | 
| 7  | *, /, `div`,   |      |     | 
|  | `mod`, `rem`, `quot` |      |     | 
| 6  | +, -     |      |     | 
| 5  |      |      | :, ++    | 
| 4  |      | ==, /=, <, <=, >, >=, |     | 
|  |      | `elem`, `notElem`  |     | 
| 3  |      |      | &&    | 
| 2  |      |      | ||    | 
| 1  | >>, >>=    |      |     | 
| 0  |      |      | $, $!, `seq`  | 
+--------+----------------------+-----------------------+-------------------+ 

Jeder Bediener eine fixity Erklärung fehlt angenommen mit Vorrang 9links assoziativ sein.

Denken Sie daran, Funktionsanwendung hat höchste Priorität (man denke an Vorrang 10 im Vergleich zu den anderen Präzedenzfälle in der Tabelle) [1].

+0

Wie kommt 'f g. h 'ist äquivalent zu 'f (g.h)'? Bedeutet dies, dass die Funktionspriorität der Anwendung niedriger oder gleich der Vorrangstellung der Funktionszusammensetzung ist? – CMCDragonkai

+0

@CMCDragonkai Ich habe die Antwort mit der Funktion Anwendungspriorität aktualisiert. 'f g. h 'ist äquivalent zu' (f g). h als Funktion hat Vorrang vor der Rangfolge aller Operatoren (einschließlich der Funktionszusammensetzung). – mucaho