This is awesome. Was wondering if it would be possible to do this more like the redux way a middleware instead of modifying the Elm core. Thought about something like:
main : Program Never Model Msg
main =
Html.program
{ init = init
, update =
update
|> withMiddleware portMiddleware
, view = view
, subscriptions = \_ -> Sub.none
}
withMiddleware :
(msg -> model -> ( model, Cmd msg ))
-> (msg -> model -> ( model, Cmd msg ))
-> (msg -> model -> ( model, Cmd msg ))
withMiddleware middleware upd msg model =
let
( updatedModel, cmd ) =
upd msg model
( mwUpdatedModel, mwCmd ) =
middleware msg updatedModel
in
( mwUpdatedModel, Cmd.batch [ cmd, mwCmd ] )
portMiddleware : Msg -> Model -> ( Model, Cmd Msg )
portMiddleware msg model =
( model, sendUpdate (encodeUpdate msg model) )
port sendUpdate : Value -> Cmd msg
encodeUpdate : Msg -> Model -> Value
encodeUpdate msg model =
Encode.object
[ ( "model", encodeModel model )
, ( "msg", encodeMsg msg )
]
The problem is now you’d have to write encoders for your Msg and Model types. Would be cool to try to do something with parsing the output of toString maybe, to have a sort of generic encoder.
Anyway, really cool stuff!