2010-03-02 21 views
9

Wenn dies funktioniert:Haskell Funktion Zusammensetzung Frage

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

Dann, warum dies nicht der Fall ist?

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

Operator Vorrang. Funktionsanwendung "bindet" sehr eng; (.) bindet sehr schwach. – jrockway

+0

'(.)' Bindet sehr eng (Vorrang = 9), aber Funktion Anwendung bindet noch enger (Priorität = 10). Fügen Sie einfach '$' zwischen den beiden Strings ein, um es zu beheben. '$' hat eine sehr niedrige Priorität, ** 0 **. –

Antwort

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

als analysiert: Das funktioniert nicht, weil das zweite Argument zu . Bedürfnisse

(map toUpper) . ((++) "sdfsd" "dfgfdg") 
Also im Grunde

Sie

(map toUpper) . "sdfsddfgfdg" 

tun eine Funktion sein, keine Zeichenfolge.

Ich nehme an, Sie haben versucht, etwas mehr wie (map toUpper . (++)) "sdfsd" "dfgfdg" zu tun. Dies funktioniert auch nicht, da der Rückgabetyp ++[a] -> [a] ist, während der Argumenttyp map toUpper[a] ist.

Die Sache hier ist, dass, während man ++ als eine Funktion denken könnte, die zwei Listen nimmt und eine Liste zurückgibt, ist es wirklich eine Funktion, die eine Liste nimmt und dann eine Funktion zurückgibt, die eine andere Liste nimmt und eine Liste zurückgibt. Um zu bekommen, was Sie wollen, müssen Sie ++ in eine Funktion, die ein Tupel von zwei Listen nimmt und eine Liste zurückgibt. Das nennt man uncurrying. Die folgenden Werke:

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

Nach Ihrer Erklärung sollte '(map toUpper. (++) "sdfsd") "dfgfdg"' die Aufgabe erledigen. Und es tut es. Vielen Dank. – artemave

+1

Und Fehlermeldung macht jetzt Sinn. Danke noch einmal. – artemave

7

Sie wollen $ statt .: map toUpper $ (++) "sdfsd" "dfg" funktioniert und das tut, was Sie wollen. Der Grund dafür ist, dass $ eine Anwendung mit sehr niedriger Priorität ist, daher lautet die korrigierte Version wie folgt: "Wenden Sie die Funktion map toUpper auf das Ergebnis (++) "sdfsd" "dfg" an".