2010-03-02 17 views
9

Se questo funziona:funzione Haskell composizione domanda

Prelude Data.Char> map toUpper ("sdfsd" ++ "dfgfdg") 
"SDFSDDFGFDG" 

Allora perché questo non lo fa?

Prelude Data.Char> map toUpper . (++) "sdfsd" "dfgfdg" 

<interactive>:1:14: 
    Couldn't match expected type `a -> [Char]' 
      against inferred type `[Char]' 
    In the second argument of `(.)', namely `(++) "sdfsd" "dfgfdg"' 
    In the expression: map toUpper . (++) "sdfsd" "dfgfdg" 
    In the definition of `it': it = map toUpper . (++) "sdfsd" "dfgfdg" 
+1

Precisione dell'operatore. L'applicazione della funzione "lega" molto strettamente; (.) si lega molto debolmente. – jrockway

+0

'(.)' Si lega molto strettamente (precedenza = 9), ma l'applicazione della funzione si lega ancora più stretta (precedenza = 10). Basta inserire '$' tra le due stringhe per risolverlo. '$' ha una precedenza molto bassa, ** 0 **. –

risposta

13
map toUpper . (++) "sdfsd" "dfgfdg" 

viene analizzato come:

(map toUpper) . ((++) "sdfsd" "dfgfdg") 

Quindi, in pratica si sta facendo

(map toUpper) . "sdfsddfgfdg" 

Questo non funziona perché il secondo argomento per . deve essere una funzione, non una stringa.

Presumo che stavate cercando di fare qualcosa di più come (map toUpper . (++)) "sdfsd" "dfgfdg". Anche questo non funziona perché il tipo restituito di ++ è [a] -> [a] mentre il tipo di argomento di map toUpper è [a].

La cosa qui è che mentre si potrebbe pensare a ++ come una funzione che prende due liste e restituisce una lista, è davvero una funzione che prende una lista e quindi restituisce una funzione che prende un'altra lista e restituisce una lista. Per ottenere ciò che desideri, devi inserire ++ in una funzione che richiede una tupla di due elenchi e restituisce un elenco. Questo è chiamato uncurrying. Le seguenti opere:

map toUpper . (uncurry (++)) $ ("sdfsd", "dfgfdg") 
+5

Dopo la tua spiegazione, '(map toUpper. (++) "sdfsd") "dfgfdg"' dovrebbe fare il lavoro. E lo fa. Grazie. – artemave

+1

E il messaggio di errore ha ora senso. Grazie ancora. – artemave

7

Volete $ invece di .: map toUpper $ (++) "sdfsd" "dfg" opere e fa ciò che vuoi. La ragione di ciò è che $ è un'applicazione con funzione di precedenza molto bassa, pertanto la versione corretta è la seguente: "Applicare la funzione map toUpper al risultato di (++) "sdfsd" "dfg"".