2010-05-14 12 views
14

Cerco di sviluppare una semplice funzione media in Haskell. Questo sembra funzionare:Operatore Haskell dot

lst = [1, 3] 

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

z = x/y 

Ma perché non fa i seguenti lavori versione?

lst = [1, 3] 

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

z = x/y 
+1

E dal momento che si sta calcolando la media, si prega di leggere http://stackoverflow.com/questions/2376981/haskell-types-frustrating-a-simple-average-function/2380437 # 2.380.437. – kennytm

risposta

16

Sei inciampato dalle regole di precedenza di haskell per gli operatori, che sono confuse.

Quando si scrive

x = fromIntegral.sum lst 

Haskell vede che come lo stesso:

x = fromIntegral.(sum lst) 

Cosa si intende scrivere era:

x = (fromIntegral.sum) lst 
+8

Questo è vero. Ma penso che scrivere operatori senza spazi attorno a loro a volte porti a fraintendimenti (ad esempio, sembra simile alla costruzione dell'accesso dei membri in molte lingue OOP-centric). '(fromIntegral. sum)' può causare domande, ma non fraintendere. – ony

+1

Per essere onesti, ciò che confonde qui non è le regole di precedenza di Haskell (che sono facili da definire) ma la sconcertante (per i principianti) schiera di operatori, ciascuno con la propria precedenza, definita nel Preludio. – sigfpe

17

. (composizione) ha una precedenza inferiore applicazione funzione, così

fromIntegral.sum lst 

viene interpretato come

fromIntegral . (sum lst) 

che è errata poiché sum lst non è una funzione.

10

Volevo solo aggiungere "$ per il salvataggio! ":

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

Ha la precedenza più bassa ed è lì per evitare troppi livelli di parentesi. Nota che a differenza di (.), Non fa la funzione di composizione, valuta l'argomento a destra e lo passa alla funzione a sinistra. Il tipo dice tutto:

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

E potresti anche scrivere 'x = fromIntegral. somma $ lst', che è ancora più vicina a ciò che l'OP inizialmente aveva provato. – yatima2975

+0

Non è * abbastanza * accurato dire che valuta l'argomento a destra. La valutazione è ancora pigra. Per valutare l'argomento, dovresti invece '$!'. – Chuck

+0

Sebbene questa soluzione funzioni, non penso che sia la risposta giusta qui. A me sembra che l'OP sia confuso sulla precedenza degli operatori. Quindi la risposta è di indicare la giusta precedenza e di sottolineare che le parentesi aiutano qui. Non presentare ancora un altro operatore. – Martijn