2016-05-20 6 views
8

Ich bin sehr neu und versuche gerade Elm zu lernen. Ich komme von JS/React und hatte noch keine RFP Erfahrung.Elm "Typ" -Syntax - Woher kommt der Wert?

Ich bin im Guide hier: http://guide.elm-lang.org/architecture/user_input/text_fields.html

Der Teil Ich habe Probleme mit sich update und view:

-- UPDATE 

type Msg 
    = Change String 

update : Msg -> Model -> Model 
update msg model = 
    case msg of 
    Change newContent -> 
     { model | content = newContent } 


-- VIEW 

view : Model -> Html Msg 
view model = 
    div [] 
    [ input [ placeholder "Text to reverse", onInput Change ] [] 
    , div [] [ text (String.reverse model.content) ] 
    ] 

Beginnen wir mit der Msg Erklärung beginnen. Der Führer sagt:

Es ein Argument, in diesem Fall ist die Änderungsfunktion, die war erstellt, als wir die Nachricht Typ deklariert:

ändern: String -> Msg

I don Wie sieht das hier aus?

type Msg 
    = Change String 

Wie haben wir hier eine Change-Funktion definiert? Wie haben wir definiert, wie diese Funktion funktioniert? Für mich sieht es so aus, als hätten wir gerade den Typ von Msg deklariert, der irgendwie was auch immer Change enthält und der Typ String ist.

Meine zweite Frage ist über das Update:

update : Msg -> Model -> Model 
update msg model = 
    case msg of 
    Change newContent -> 
     { model | content = newContent } 

Für mich sieht aus wie eine Update Funktion höherer Ordnung, das eine Msg nimmt und gibt eine Funktion Model -> Model. Dann definieren wir eine Funktion mit zwei Parametern. Bedeutet Msg -> Model -> Model nur, dass alle außer dem letzten Teil Parameter sind?

Dann rufen wir die Change Funktion:

Change newContent -> 
      { model | content = newContent } 

Was ich nicht bekommen, gibt es den Pfeil. Normalerweise kommt der Pfeil nach einer Paramdefinition. Aber hier haben wir das Ergebnis einer Funktion vor der ->.

Ich hoffe meine Fragen ergeben Sinn, ich bin nur sehr verwirrt mit dieser (vermutlich ehrfürchtigen) Sprache.

Antwort

4

Wenn Sie type Msg = Change String deklarieren, deklarieren Sie einen einzelnen Typ (Msg) mit einem Konstruktor, der einen String akzeptiert.

Siehe Elm Guide Abschnitt Union Types (AKA Algebraische Datentypen, ADTs).

Hier ist ein Beispiel:

type User = Anonymous | Named String 

So die Art zu schaffen User auch Konstrukteuren erstellt namens Anonymous und Named.Wenn Sie eine User erstellen möchten, müssen Sie eine dieser beiden Konstrukteure verwenden

Konstrukteurs-Funktionen sind, so dass man sie nennen wie Change "a string" (kehrt Typ Msg)

Konstrukteurs auch die Möglichkeit bieten, Musteranpassung zu verwenden,, um den inneren Wert in einem Union-Typ zu extrahieren. Dies ist die Verwendung von ->, mit der Sie nicht vertraut waren.

case msg of 
    Change theString -> ... use theString ... 

Ihre zweite Frage;

Für mich sieht aus wie eine Update Funktion höherer Ordnung, das eine Nachricht nimmt und gibt eine Funktion Model -> Modell

Ja, das ist mehr oder weniger, was passiert. Die Vorrangregeln für die Funktionsanwendung bedeuten, dass Sie sie ohne Klammern aufrufen können. Dies nennt man currying, und es ist auch in der Ulme Führung bedeckt

2

Nur ein bisschen mehr um den zweiten Teil zu klären:

Alle Funktionen curried werden, was bedeutet, dass update: Msg->Model->Model eine Msg empfangen und geben eine Funktion Model->Model oder erhalten Sie eine Msg und eine Model und eine Model zurück.

In Wirklichkeit, wenn Sie anrufen update aMessage aModel Sie wirklich update aMessage fordern, die eine Funktion zurückgibt und dann übergeben Sie aModel zu dieser Funktion, die die Ausdrücke in den Körper der Funktion und zurück das aktualisierte Modell ausgeführt wird.

Der Pfeil ist nur ein Teil der case.. of Syntax. Die linke Seite ist das Muster, das Sie zuordnen möchten, die rechte Seite ist der Ausdruck, den Sie ausführen möchten. In Ihrem Fall führt Ihr Update den Ausdruck nur dann aus, wenn die Nachricht mit dem Konstruktor Change erstellt wurde.

type Msg 
    = Change String | Delete 

update : Msg -> Model -> Model 
update msg model = 
    case msg of 
    Change newContent -> 
     { model | content = newContent } 
    Delete -> 
     { model | content = "" } 

Im vorherigen Fall kann entweder mit Msg Change String oder mit Delete konstruiert werden. Die Aktualisierungsfunktion verhält sich je nach Aufbau der Nachricht unterschiedlich.