2017-05-11 3 views
3

Ausgehend von diesen drei Erklärungen:Gibt es in Elm eine Möglichkeit, Unionstypen zusammenzuführen? (Modularität Zweck)

type SharedMsg 
    = SharedAction 

type Page1Msg 
    = Page1Action 

type Page2Msg 
    = Page2Action 

ich es eine Möglichkeit, ein Äquivalent des folgenden eines zu erhalten? Wie eine Möglichkeit, Unionstypen zu "verschmelzen"?

type Msg 
    = SharedAction 
    | Page1Action 
    | Page2Action 

=============================

Kontext: I in eine ELM Anwendung am Aufspalten Modul pro Seite mit eigenen Ordnern.

Einige Aktionen werden freigegeben und einige Aktionen sind seitenspezifisch.

Wenn ich die Html.map Methode zu verwenden war, habe ich das Gefühl, dass ich jede gemeinsame Aktion, die eine Seite verwendet in seiner eigenen PageMsg Nachrichtentyp neu schreiben müsste:

type Page1Msg 
    = Page1Action 
    | SharedAction 

type Msg 
    = Page1Msg Page1Msg 
    | Page2Msg Page2Msg 

view : Model -> Html Msg 
view = 
    Html.map Page1Msg (Page1View.view model) 

Daher meine Gedanken an eine Verwendung Unique Msg Typ für alle Seiten, aber Wahrung der Modularität durch Schreiben von seitenspezifischen Nachrichten in ihren eigenen Ordnern, und dann irgendwie definieren einen eindeutigen Msg Typ durch Zusammenführen von ihnen.

+1

Sind diese Seiten in einer Single Page App? Welche Art von geteilten Nachrichten haben Sie und wo entstehen sie? Damals, als die Elm-Community versuchte, diese Fragen herauszufinden, schrieb ich ein Stück über Medium (https://medium.com/@alex.lew/the-translator-pattern-a-model-for-child-to- parent-communication-in-elm-f4bfaa1d3f98) über meine Lösung für das Problem von Page1 und Page2 beide in der Lage sein, einige gemeinsame Nachricht in der "übergeordneten" Update-Funktion auslösen. Aber das Denken der Gemeinschaft hat sich seitdem weiterentwickelt, und wenn Sie die Besonderheiten Ihres Falles kennen, könnte dies eine bessere Lösung sein! –

+1

(Ich sollte erwähnen, dass es keine Möglichkeit gibt, Union-Typen zu verschmelzen, wie Sie es versuchen, ohne neue Tags/Konstruktoren zu erstellen.) –

+0

1. Danke für die Antwort über die Verschmelzung von Typen und 2. Wow super intelligente Übersetzer Muster, ich Ich werde in diese Richtung graben! Die freigegebenen Nachrichten, an die ich gedacht habe, sind von der gleichen Art wie die, die Sie erwähnen: Zeigen Sie einen globalen App-Lade-Spinner an, laden Sie geteilte Cross-Seiten-Daten ... – AlexHv

Antwort

3

@ z5h das ist fast richtig , aber die Typkonstruktoren müssen unterschiedliche Namen haben.

Sie können die Typen nicht so zusammenführen, wie Sie möchten.

Wie für den idiomatischen Weg: Sie würden die Split-Typen nur Msg, nicht Page1Msg nennen. So zum Beispiel:

Page1.Ulme:

module Page1 exposing (Msg) 

type Msg 
    = Foo 

Page2.elm:

module Page2 exposing (Msg) 

type Msg 
    = Bar 

Shared.elm:

module Shared exposing (Msg) 

type Msg 
    = Baz 

Main.elm:


By the way, daran erinnert, dass, wenn Sie die Module in Page1.View aufgeteilt, Page1.Types usw., dann solange die freiliegenden Funktionen nicht überlappen, können Sie verschiedene Module unter dem gleichen Namen importieren, dh:

import Page1.Types as Page1 
import Page1.State as Page1 
import Page1.View as Page1 
import Page1.Decoders as Page1 
+0

Das Schwierige ist, in diesem Fall eine Ansichtsfunktion für Page1 zu schreiben. Hast du Html.map die Ausgabe? Mit welcher Funktion? Vielleicht kann die View-Funktion die Konstruktoren SharedMsg und Page1Msg als Argumente akzeptieren? –

+0

'Page1.view: Page1.Model -> Html Page1.Msg', Verwendung von Main:' Main.view mainModel = Html.map Page1Msg (Page1.view mainModel.page1Model) ' –

+1

Aber dann wie' Page1.view' eine gemeinsame Nachricht erzeugen? –

0

Das Problem ist, haben Sie gesagt:

type SharedMsg 
    = SharedAction 

So wissen wir, die Art der SharedAction ein SharedMsg ist.
Aber dann sagen Sie:

type Msg 
    = SharedAction 
    | Page1Action 
    | Page2Action 

So, jetzt ein Widerspruch, dass SharedAction ist ein Msg.

Der einfache Weg, dies zu umgehen ist zu sagen:

type Msg 
    = Msg SharedMsg 
    | Msg Page1Msg 
    | Msg Page2Msg 

D.h. Msg ist ein Konstruktor, dessen Instanzen vom Typ Msg sind, der die folgenden Werte haben kann.

+2

Das letzte Codebeispiel wird nicht funktionieren. Die Konstruktoren müssen unterschiedliche Namen haben, d. 'Typ A = A1 Foo | A2 Bar | A3 Baz' statt 'Typ A = A Foo | Eine Bar | A Baz' –

2

Vergessen Sie nicht, dass Sie absolut nicht verpflichtet sind, die update-view-Definitionen genau wie in den grundlegenden Beispielen zu befolgen. In Ihrem Fall könnten Sie die Update-Funktion auf Ihre Bedürfnisse

wie etwa in Mutter anpassen:

update message model = 
    let 
     sharedMsgs = 
      { msg1 = Msg1 
      , msg2 = Msg2 
      } 

    in case message of 
     Page1Msg msg -> 
      let (m, c) = 
       update sharedMsgs msg model.page1 
      in case c of 
       Nothing -> 
        m 
       Just c -> 
        update c m 

wo die Update-Funktion in page1 Signatur Antwort hat

update : SharedMessages msg -> Msg -> Page1Model -> (Page1Model, Maybe msg) 
Verwandte Themen