Skip to content

Modules in V2 #896

@zaceno

Description

@zaceno

💁‍♂ Check out the current proposal here.


Consider this minimal example of a modular Elm app (copied from here):

Button.elm
module Button exposing (Model, Msg(..), init, update, view)

import Html exposing (Html, button, div, h1, text)
import Html.Events exposing (onClick)



-- MODEL


type alias Model =
    Int


init : Model
init =
    0



-- UPDATE


type Msg
    = Increment
    | Decrement


update : Msg -> Model -> Model
update msg model =
    case Debug.log "Button.update msg: " msg of
        Increment ->
            model + 1

        Decrement ->
            model - 1


view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Decrement ] [ text "-" ]
        , div [] [ text (String.fromInt model) ]
        , button [ onClick Increment ] [ text "+" ]
        ]
Main.elm
type alias Model =
    { button : Button.Model }


init : Model
init =
    { button = Button.init
    }



-- UPDATE


type Msg
    = ButtonMsg Button.Msg


update : Msg -> Model -> Model
update msg model =
    case Debug.log "update msg" msg of
        ButtonMsg buttonMsg ->
            { model | button = Button.update buttonMsg model.button }



-- VIEW


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text "elm button example" ]
        , map ButtonMsg (Button.view model.button)
        ]

Notice two things:

A) Increment and Decrement are completely unaware of the shape of the global app state. Their definitions are completely self contained.

B) Main.elm never once explicitly references Increment or Decrement.

As far as I've been able to tell, this is not possible to achieve using Hyperapp 2. You can have A or B but not both. This has frightening implications for large scale apps.

I would like to see a convention, add-on library or core change -- or some combination of all three -- which enabled us to replicate the example above in Hyperapp v2.

That essentially means being able to use a module which defines its actions in a self-contained, app-agnostic way, without being required to export them. They should not need to be explicitly referenced anywhere else.

Additionally, whatever we come up with, I would also want it to work in a recursive fashion, that is to say: a module can use a module which uses modules ...

EDIT: Also, of course, this shouldn't just apply to actions dispatched from views. It should be the same for actions dispatched from Effects (whatever action initiated the effect), and subscriptions.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions