Applikative Funktoren: Warum kann fmap eine Funktion mit mehr als einem Argument aufnehmen?

8

Ich steige in Haskell ein und finde das Buch "lerne dir ein Haskell" am hilfreichsten. Ich bin auf dem Abschnitt auf applicative Funktoren .

Ich bin verwirrt über das Folgende, wie es in dem Buch erscheint:

%Vor%

was die Ausgabe ergibt:

%Vor%

Erstens habe ich meinen Verdacht in ghci bezüglich der Vorrangstellung der Operatoren bestätigt, so dass das obige die folgende hässliche Aussage darstellt:

%Vor%

Daraus wird klar, dass das erste, was passiert, der Aufruf fmap über den Infixoperator (<$>) ist.

Und das ist der Kern dessen, was mich derzeit verrückt macht. Die Definition von fmap (hier als Infix (<$>) dargestellt) lautet:

%Vor%

Aber in der Gleichung, mit der ich kämpfe, braucht (\x y z -> [x, y, z]) drei Argumente, nicht nur eins. Wie könnte also das erste Argument vom Typ (a -> b) erfüllt sein?

Ich denke, es könnte mit partieller Anwendung / Currying zu tun haben, aber ich kann es nicht herausfinden. Ich würde eine Erklärung sehr schätzen. Hoffe ich habe die Frage gut genug formuliert.

    
Felix Schlitter 27.01.2014, 08:31
quelle

4 Antworten

11

Einfache Antwort: Es gibt keine Funktionen mit mehreren Argumenten in Haskell!

Es gibt zwei Kandidaten für das, was man "dyadische Funktion" nennen könnte: eine Funktion, die ein (einzelnes!) Tupel und - weit verbreitet in Haskell - curried-Funktionen verwendet. Diese nehmen nur ein Argument, aber das Ergebnis ist wieder eine Funktion.

Also, um herauszufinden, was z.B. fmap (+) macht, lass uns schreiben

%Vor%

Testen Sie es selbst in GHCi:

  

Vorspiel & gt; Typ IntF = Int - & gt; Int
  Auftakt & gt; let (#) = (+) :: Int - & gt; IntF
  Auftakt & gt; : t fmap (#)
  fmap (#) :: Functor f = & gt; f Int - & gt; f IntF

    
leftaroundabout 27.01.2014 08:37
quelle
7

Betrachten Sie eine Funktion vom Typ

%Vor%

wobei d ein anderer Typ ist. Aufgrund des Curry kann dies als eine Funktion mit dem folgenden Typ betrachtet werden:

%Vor%

d. Eine Funktion, die ein a übernimmt und eine Funktion vom Typ b -> c -> d zurückgibt. Wenn Sie fmap anwenden, haben Sie

%Vor%

Dies ist jetzt der richtige Typ, der als linkes Argument für (<*>) verwendet wird.

    
Chris Taylor 27.01.2014 08:37
quelle
3

Da Sie eine 3-Argument-Funktion verwenden können, geben Sie ihr nur ein Argument vor. Dies führt zu einer 2-Argument-Funktion. Sie werden also mit einer Liste von 2-Argument-Funktionen enden. Sie können dann ein weiteres Argument anwenden, mit einer Liste von 1-Argument-Funktionen enden und schließlich das letzte Argument anwenden, woraufhin Sie eine Liste mit gewöhnlichen Zahlen erhalten.

Das ist übrigens warum Haskell Curry-Funktionen hat. Es macht es einfach, Konstrukte wie diese zu schreiben, die für eine beliebige Anzahl von Funktionsargumenten funktionieren. : -)

    
MathematicalOrchid 27.01.2014 09:08
quelle
2

Ich persönlich finde die applikative Funktorinstanz für Funktionen etwas seltsam. Ich werde Sie durch dieses Beispiel führen, um intuitiv zu verstehen, was vor sich geht:

%Vor%

Dies gilt (+3) auf den ersten Parameter der inneren Funktion. Die anderen 2 äußeren Parameter werden unmodifiziert an die innere Funktion übergeben.

Fügen wir ein Anwendungsbeispiel hinzu:

%Vor%

Dies gilt (+3) auf das erste Argument wie zuvor. Mit dem applicative wird der erste äußere Parameter ( 1 ) (*2) angewendet und als zweiter Parameter der inneren Funktion übergeben. Der zweite äußere Parameter wird als dritter Parameter unmodifiziert an die innere Funktion übergeben.

Raten Sie, was passiert, wenn wir eine andere Anwendung verwenden:

%Vor%

3 Anwendungen für denselben Parameter übergeben 3 Argumente an die innere Funktion.

Es ist keine theoretisch solide Erklärung, aber es kann eine Intuition darüber geben, wie die anwendbare Instanz von Funktionen funktioniert.

    
Danny Navarro 27.01.2014 09:24
quelle

Tags und Links