2010-05-14 11 views
14

J'essaie de développer une fonction moyenne simple dans Haskell. Cela semble fonctionner:Opérateur point Haskell

lst = [1, 3] 

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

z = x/y 

Mais pourquoi ne fonctionne pas la version suivante?

lst = [1, 3] 

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

z = x/y 
+1

Et puisque vous calculer la moyenne, s'il vous plaît lire http://stackoverflow.com/questions/2376981/haskell-types-frustrating-a-simple-average-function/2380437 # 2380437 – kennytm

Répondre

16

Les règles de priorité d'Haskell pour les opérateurs vous font trébucher, ce qui est source de confusion.

Lorsque vous écrivez

x = fromIntegral.sum lst 

Haskell voit que la même chose que:

x = fromIntegral.(sum lst) 

Qu'est-ce que vous vouliez écrire était:

x = (fromIntegral.sum) lst 
+8

C'est vrai. Mais je pense que l'écriture d'opérateurs sans espaces autour d'eux conduit parfois à un malentendu (c'est-à-dire qu'il ressemble à la construction d'un membre accédant dans de nombreux langages OOP-centric). '(fromIntegral. sum)' peut provoquer des questions, mais pas une mauvaise interprétation. – ony

+1

Pour être honnête, ce qui est déroutant ici, ce ne sont pas les règles de préséance d'Haskell en elles-mêmes (qui sont faciles à énoncer) mais le déroutant (au débutant) tableau d'opérateurs, chacun avec leur propre préséance définie dans le Prélude. – sigfpe

17

. (composition) a une priorité plus faible que la demande de fonction, de sorte

fromIntegral.sum lst 

est interprété comme

fromIntegral . (sum lst) 

qui est erroné puisque sum lst est pas une fonction.

10

Je voulais juste ajouter "$ à la rescousse! ":

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

Il a la priorité la plus basse et il est là pour éviter trop de niveaux de parenthèses. Notez que contrairement à (.), Il ne fait pas de composition de fonction, il évalue l'argument à droite et le passe à la fonction de gauche. Le type dit tout:

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

Et vous pouvez aussi écrire 'x = fromIntegral. sum $ lst' qui est encore plus proche de ce que le PO a essayé à l'origine. – yatima2975

+0

Il n'est pas tout à fait exact de dire qu'il évalue l'argument à droite. L'évaluation est encore paresseuse. Afin d'évaluer l'argument, vous voudriez '$!' À la place. – Chuck

+0

Bien que cette solution fonctionne, je ne pense pas que ce soit la bonne réponse ici. Pour moi, il semble que le PO est confus au sujet de la préséance des opérateurs. Alors la réponse est d'indiquer la préséance appropriée et de souligner que les parenthèses aident ici. Ne pas présenter encore un autre opérateur. – Martijn