2017-07-11 3 views
2

Das erste Argument, dass fmap erwartet wird, ist eine Funktion mit einem Argument.Zu viele Argumente für fmap

fmap :: Functor f => (a -> b) -> f a -> f b 

Dann habe ich versucht, wie in Vorspiel folgen:

Prelude> x = fmap (\x y -> x * y) 

Wie Sie das erste Argument fmap eine Funktion sehen können, ist, die zwei Argumente hat. Warum lässt der Compiler es passieren?

Die Funktion, die ich an fmap oben übergeben habe, hat zwei Argumente nicht eins!

+3

Denn in Haskell gelten alle Funktionen als curried – Khundragpan

+0

Dies ist Abstraktion über Arity, die mit Sprachen, die su sind, möglich ist pport erstklassige Funktionen. Anstatt auf die Funktion einer Multi-Argument-Funktion achten zu müssen, müssen Sie den Funktionsablauf im Auge behalten. – ftor

+0

Dies ist eigentlich eine sehr häufige Sache in Haskell mit Applikaten zu tun. 'f <$> x <*> y 'bedeutet' fmap f x <*> y'. Zum Beispiel bedeutet '(*) <$> [2, 3] <*> [5, 7]' '[(2 *), (3 *)] <*> [5, 7]', was zu '[2 * 5, 2 * 7, 3 * 5, 3 * 7] 'oder' [10, 14, 15, 21] '. –

Antwort

9

Haskell hat eigentlich keine Funktionen mit mehr (oder weniger) als einem Argument. Eine "Zwei-Argument-Funktion" ist eigentlich nur eine Funktion, die ein Argument benötigt und eine andere Funktion erzeugt, die ein anderes Argument annimmt. Das heißt, \x y -> x * y ist nur eine syntaktische Abkürzung für \x -> \y -> x * y. Dieses Konzept wird als Curry bezeichnet.

Das sollte also erklären, was in Ihrem Beispiel passiert. Ihr fmap wird einfach eine f von Zahlen in eine f von Funktionen verwandeln. So würde zum Beispiel x [1,2,3] die Liste [\y -> 1 * y, \y -> 2 * y, \y -> 3 * y] (a.k.a. [(1*), (2*), (3*)]) erzeugen.

2

Sie haben eine Funktion definiert. Einer der grundlegenden Aspekte der funktionalen Programmierung, die Funktionen Parameter sein kann, in Variablen gespeichert, usw.

Wenn wir dann abfragen, um den Typ von x, erhalten wir:

Prelude> :t x 
x :: (Functor f, Num a) => f a -> f (a -> a) 

So x ist jetzt ein Funktion, die eine Functor mit a übernimmt, die auf diese Funktion angewendet wird, und gibt das Element eines Typs mit demselben Funktor zurück, aber angewendet mit a -> a.

So können Sie zum Beispiel eine Liste auf x anwenden, wie:

Prelude> :t x [1,4,2,5] 
x [1,4,2,5] :: Num a => [a -> a] 

So, jetzt haben wir eine Liste der Funktionen, dh Äquivalent zu:

[\x -> 1*x, \x -> 4*x, \x -> 2*x, \x -> 5*x]