Ich liebe Elm wirklich, bis zu dem Punkt, an dem ich auf eine Funktion stoße, die ich noch nie zuvor gesehen habe und die seine Eingaben und Ausgaben verstehen möchte.
Nehmen Sie die Deklaration von foldl
zum Beispiel:
Ich schaue mir das an und kann mir nicht helfen, als gäbe es eine Reihe von Klammern, die ich vermisse, oder eine andere Subtilität über die Assoziativität dieses Operators (für die ich keine explizite Dokumentation finde). Vielleicht ist es nur eine Frage der Verwendung der Sprache mehr, bis ich nur ein "Gefühl" dafür bekomme, aber ich würde gerne denken, dass es eine Möglichkeit gibt, diese Definition auf Englisch zu "lesen".
Schauen Sie sich das Beispiel aus den Dokumenten ... Ich erwarte, dass die Funktionssignatur etwas wie folgt liest: Wenn eine Funktion eine Stimmt das? Welchen Rat können Sie jemandem wie mir geben, der verzweifelt möchte, dass Eingaben durch Kommata getrennt werden und Eingaben / Ausgaben klarer getrennt werden?
a
und eine b
verwendet und eine b
zurückgibt, gibt eine zusätzliche b
und eine List
, foldl
eine b
zurück.
Die fehlenden Klammern, die Sie suchen, sind darauf zurückzuführen, dass ->
rechtsassoziativ ist: Der Typ (a -> b -> b) -> b -> List a -> b
entspricht (a -> b -> b) -> (b -> (List a -> b))
. Informell, in einer Kette von ->
s, lies alles vor der letzten ->
als Argument und nur die rechte Sache als Ergebnis.
Die Schlüsseleinblicke, die Ihnen vielleicht fehlen, sind currying - die Idee, wenn Sie eine Funktion haben, die zwei Argumente braucht Sie können es mit einer Funktion darstellen, die das erste Argument übernimmt und eine Funktion zurückgibt, die das zweite Argument übernimmt und das Ergebnis zurückgibt.
Angenommen, Sie haben eine Funktion add
, die zwei ganze Zahlen benötigt und sie addiert. In Elm könnten Sie eine Funktion schreiben, die beide Elemente als Tupel verwendet und fügt sie hinzu:
und du könntest es als
bezeichnen %Vor%Aber angenommen, Sie hätten keine Tupel. Sie könnten denken, dass es keine Möglichkeit geben würde, diese Funktion zu schreiben, aber in der Tat könnten Sie mit currying folgendes schreiben:
%Vor% Das heißt, Sie schreiben eine Funktion, die x
übernimmt und eine andere Funktion zurückgibt, die y
übernimmt und sie der ursprünglichen x
hinzufügt. Du könntest es mit
Sie können sich nun add
auf zwei Arten vorstellen: Entweder als Funktion, die ein x
und ein y
benötigt und fügt sie, oder , als eine "Factory" -Funktion hinzu x
values und erzeugt neue, spezialisierte addx
-Funktionen, die nur ein Argument aufnehmen und zu x
hinzufügen.
Die "Fabrik" -Version der Dinge ist ab und zu nützlich. Wenn Sie beispielsweise eine Liste von Nummern mit dem Namen numbers
haben und jeder Zahl 3 hinzufügen möchten, können Sie einfach List.map (add 3) numbers
; Wenn Sie stattdessen die Tupel-Version geschrieben hätten, müssten Sie etwas wie List.map (\y -> add (3,y)) numbers
schreiben, was etwas unangenehmer ist.
Elm kommt aus einer Tradition von Programmiersprachen, die diese Art des Denkens über Funktionen wirklich mögen und sie ermutigen, wo es möglich ist. Elms Syntax für Funktionen soll es einfach machen. Zu diesem Zweck ist ->
rechtsassoziativ: a -> b -> c
entspricht a -> (b -> c)
. Das heißt, wenn Sie keine Klammern setzen, definieren Sie eine Funktion, die ein a
und ein b -> c
zurückgibt, was wir uns wiederum als eine Funktion vorstellen können, die ein a
und ein% co_de benötigt % und gibt eine b
, oder äquivalent eine Funktion zurück, die ein c
und ein a
zurückgibt.
Es gibt noch eine andere syntaktische Eigenschaft, die hilft, diese Funktionen aufzurufen: function application ist links -assoziativ. Auf diese Weise kann der hässliche b -> c
von oben als ((add 1) 2)
geschrieben werden. Mit diesem Syntax-Tweak müssen Sie gar nicht erst an Curry denken, es sei denn, Sie möchten eine Funktion teilweise anwenden - rufen Sie sie einfach mit allen Argumenten auf und die Syntax wird funktionieren.
Tags und Links elm