2013-05-02 6 views
6

Essendo un novizio di Haskell non riesco a capire il motivo per cui l'espressione head . words “one two three four” lancia una composizione un'eccezione e la funzione head . words deve essere applicato con $ operatore - l'espressione a destra di esso non lo fa bisogno di ulteriore valutazione perché è solo un singolo String. L'altro modo per compilarlo è mettere head . words tra parentesi ma lo (head . words) :: String -> String ha lo stesso tipo di head . words :: String -> String quindi perché metterlo tra parentesi rende l'espressione compilare?Applicazione di argomenti di funzionare composizione in Haskell

risposta

11

A causa delle regole di precedenza. L'applicazione ha la precedenza più alta; $ - il più basso.

head . words “one two three four” viene analizzato come head . (words “one two three four”) cioè words applicato su una stringa deve produrre una funzione (come richiesto dalla (.)). Ma non è il tipo che ha words:

Prelude> :t words 
words :: String -> [String] 

head . words $ “one two three four” d'altra parte, è analizzato come (head . words) “one two three four” ei tipi di attacco.

+0

Grazie per la risposta, è stato un po 'difficile per me capire che l'operatore di composizione è esso stesso una funzione. –

+2

@wojtek ah, sì, '(.) :: (b -> c) -> (a -> b) -> a -> c'. Non dimenticare, le frecce nel tipo di firme associano a destra. È veramente '(.) :: (b -> c) -> (a -> b) -> (a -> c)'. Immagina di avere questi due tubi, 'g :: b-> c' e' h :: a-> b'. Quindi, ovviamente, l'output di 'b' va all'input di' b': '(g.h) x = g (h x)' i.e. '(g.h) :: a-> c'. –

+1

@wojtek Ogni operatore è esso stesso una funzione e ha precedenza più bassa dell'applicazione della funzione. Questo è qualcosa che un programmatore Haskell deve assolutamente tenere a mente. – Ingo