2010-05-14 6 views
14

Ich versuche, eine einfache durchschnittliche Funktion in Haskell zu entwickeln. Dies scheint zu funktionieren:Haskell Punktoperator

lst = [1, 3] 

x = fromIntegral (sum lst) 
y = fromIntegral(length lst) 

z = x/y 

Aber warum nicht die folgende Version der Arbeit?

lst = [1, 3] 

x = fromIntegral.sum lst 
y = fromIntegral.length lst 

z = x/y 
+1

Und da man den Durchschnitt sind die Berechnung, lesen Sie bitte http://stackoverflow.com/questions/2376981/haskell-types-frustrating-a-simple-average-function/2380437 # 2380437. – kennytm

Antwort

16

Sie werden durch Haskells Vorrangregeln für Operatoren, die verwirrend sind, immer wieder in die Irre geführt.

Wenn Sie schreiben

x = fromIntegral.sum lst 

Haskell sieht, dass als das gleiche wie:

x = fromIntegral.(sum lst) 

Was Sie war zu schreiben bedeutete:

x = (fromIntegral.sum) lst 
+8

Das stimmt. Aber ich denke, das Schreiben von Operatoren ohne Leerzeichen um sie herum führt manchmal zu Missverständnissen (d. H. Es sieht ähnlich aus wie die Konstruktion des Mitgliederzugriffs in vielen OOP-zentrischen Sprachen). "(fromIntegral. sum)" kann zu Fragen führen, aber nicht zu Fehlinterpretationen. – ony

+1

Um ehrlich zu sein, ist das, was hier verwirrend ist, nicht Haskells Vorrangregeln an sich (die leicht zu sagen sind), sondern das verwirrende (für Anfänger) Array von Operatoren, jede mit ihrer eigenen Präzedenz, definiert im Prelude. – sigfpe

17

. (Zusammensetzung) eine niedrigere Priorität als Funktionsanwendung, so

fromIntegral.sum lst 

als

interpretiert wird
fromIntegral . (sum lst) 

was falsch ist, da sum lst nicht eine Funktion ist.

10

Ich wollte nur "hinzufügen $ zur Rettung! ":

x = fromIntegral $ sum lst 
y = fromIntegral $ length lst 

Es hat die niedrigste Priorität und es ist da, um zu viele Klammern Ebenen zu vermeiden. Beachten Sie, dass es im Gegensatz zu (.) Keine Funktionskomposition ausführt, sondern das Argument nach rechts auswertet und es an die Funktion auf der linken Seite weiterleitet. Der Typ sagt alles:

($) :: (a -> b) -> a -> b 
(.) :: (b -> c) -> (a -> b) -> a -> c 
+1

Und Sie könnten auch 'x = fromIntegral schreiben. sum $ lst', was noch näher an dem ist, was das OP ursprünglich versuchte. – yatima2975

+0

Es ist nicht ganz richtig zu sagen, dass es das Argument nach rechts bewertet. Bewertung ist immer noch faul. Um das Argument zu bewerten, möchten Sie stattdessen '$!'. – Chuck

+0

Obwohl diese Lösung funktioniert, glaube ich nicht, dass es die richtige Antwort hier ist. Für mich scheint es, dass die OP über die Rangfolge der Operatoren verwirrt ist. Dann ist die Antwort, die richtige Priorität anzuzeigen und darauf hinzuweisen, dass die Klammern hier helfen. Nicht, um noch einen anderen Betreiber einzuführen. – Martijn