2017-07-23 9 views
1

Ich bin immer noch ein Anfänger, wenn es um Haskell Syntax und funktionale Programmiersprachen kommt, so wenn ich die Typdeklaration für Data.Function.on betrachten, die on :: (b -> b -> c) -> (a -> b) -> a -> a -> c ist, meine Interpretation ist, dass es vier Parameter dauert: , (a -> b), a, a und gibt c zurück. Wenn ich jedoch die Syntax für allgemeine Verwendung für Data.Function.on anschaue, die (*) `on` f = \x y -> f x * f y ist, nimmt sie nur zwei Funktionsparameter, nicht vier, ab. Wie also bezieht sich die Typensignatur auf die Verwendungssyntax?Understanding Data.Function.on Typ Unterschrift

+0

Die '(->)' ist rechtsassoziativ, so '(b -> b -> c) -> (a -> b) -> a - > a -> c' ist gleichbedeutend mit '(b -> b -> c) -> (a -> b) -> (a -> a -> c)'. Beachten Sie die Klammern um das 'a -> a -> c 'am Ende. – 4castle

+0

Dies entspricht "on (*) f x y = f x * f y". – chi

Antwort

1

Der Haskell Pfeil für Funktionstypen verbirgt eine einfache, aber clevere Idee. Sie müssen an -> als Operator denken, wie + und -, aber für Typen. Es nimmt zwei Arten als Argumente und gibt Ihnen einen neuen Typ, der aus einer Funktion besteht. So in

Int -> String 

Sie haben die Typen Int und String, und Sie eine Funktion von einem Int in einen String zu bekommen.

Genau wie jeder andere Operator benötigen Sie eine Regel für eine Kette von ihnen. Wenn Sie an - denken, was bedeutet das?

10 - 6 - 4 

Bedeutet es (10 - 6) - 4 = 0, oder es 10 - (6 - 4) = 8 bedeutet? Die Antwort ist die erste, weshalb wir sagen, dass - "links assoziativ" ist.

Der -> Operator ist richtig assoziativ, so

foo :: Int -> String -> String 

bedeutet eigentlich

foo :: Int -> (String -> String) 

Überlegen Sie, was das bedeutet. Das bedeutet, dass foo keine 2 Argumente akzeptiert und ein Ergebnis vom Typ String zurückgibt. Es benötigt 1 Argument (Int) und gibt eine neue Funktion zurück, die das zweite Argument (String) übernimmt und das letzte String zurückgibt.

Funktion Anwendung funktioniert auf die gleiche Weise, außer dass assoziativ gelassen wird.So

foo 15 "wibble"

bedeutet eigentlich

(foo 15) "wibble"

foo So wird 15 angewendet und gibt eine neue Funktion, die dann auf "wibble" aufgebracht ist.

Dies führt zu einem netten Trick: anstatt alle Parameter beim Aufruf einer Funktion angeben zu müssen (wie Sie es in fast jeder anderen Programmiersprache tun), können Sie einfach die erste oder die ersten paar angeben Holen Sie sich eine neue Funktion zurück, die den Rest der Parameter erwartet.

Dies ist, was passiert mit on. Ich werde eine konkretere Version verwenden, bei der 'f' durch 'length' ersetzt wird.

(*) on Länge

Sie on seine ersten beiden Parameter geben. Das Ergebnis ist eine neue Funktion, die die anderen beiden erwartet. Bei den Typen,

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c 

In diesem Fall (*) hat Num n => n -> n -> n Typ (I verschiedenen Buchstaben bin mit dieser weniger verwirrend machen), so dass mit dem Typ des ersten Arguments zu on abgestimmt, zu dem Schluss führt, dass Wenn der Typ b durch n ersetzt wird, dann muss der Typ c auch so sein und muss auch eine Num Instanz sein. Daher muss length einen numerischen Typ zurückgeben. Wie es der Fall ist der Typ length ist [d] -> Int, und Int ist eine Instanz von Num, so dass funktioniert. So am Ende dieses erhalten Sie:

(*) `on` length :: [d] -> [d] -> Int 
3

meine Interpretation ist, dass es vier Parameter

Alle Haskell Funktionen übernehmen ein Argument. Einige von ihnen geben nur andere Funktionen zurück.

Der beste Weg, um die Signatur für on zu betrachten, ist als eine Funktion höherer Ordnung: (b -> b -> c) -> (a -> b) -> (a -> a -> c). Dieses sagt "wenn Sie mir einen binären Operator geben, der b s nimmt und c gibt und eine Weise, b s von a s zu erhalten, gebe ich Ihnen einen binären Operator, der a s nimmt und eine c gibt". Sie können dies in der Definition sehen: