Chadtech / return / Return3

This package makes it easier to build (module, Cmd msg, reply) a common return value for big sub-modules. See the readme for an explanation of what Return3 is all about.

Return


type alias Return model msg reply =
( model
, Platform.Cmd.Cmd msg
, Maybe reply 
)

This alias formalizes that this particular triple is our return value.

With

withReply : reply -> ( model, Platform.Cmd.Cmd msg ) -> Return model msg reply

Add a reply to your tuple.

model
    |> R2.withNoCmd
    |> R3.withReply UserNameChanged

withNoReply : ( model, Platform.Cmd.Cmd msg ) -> Return model msg reply

Dont add a reply to your tuple.

FetchingData
    |> R2.withCmd getLocalStorage
    |> R3.withNoReply

withTuple : ( model, Platform.Cmd.Cmd msg ) -> reply -> Return model msg reply

If building your reply takes a lot of work, use this function.

calculate width height x y
    |> center model.size
    |> UpdateSpace
    |> R3.withTuple
        (model |> R2.withNoCmd)

withNothing : model -> Return model msg reply

Return the model with no cmd and no reply

model
    |> withNothing

Add

addCmd : Platform.Cmd.Cmd msg -> Return model msg reply -> Return model msg reply

Sometimes you need to add a cmd to an already packaged Return

(model, cmd0, reply)
    |> addCmd cmd1

    -- == (model, Cmd.batch [ cmd1, cmd0 ], reply)

addCmds : List (Platform.Cmd.Cmd msg) -> Return model msg reply -> Return model msg reply

Add many cmds to an already packaged Return

(model, cmd0, reply)
    |> addCmds [ cmd1, cmd2 ]

    -- == (model, Cmd.batch [ cmd0, cmd1, cmd2 ], reply)

Map

mapModel : (a -> b) -> Return a msg reply -> Return b msg reply

If you need to transform just the model in a Return, such as if you need to pack a submodel into the main model

loginModel
    |> Login.update subMsg
    |> mapModel (setPage model Page.Login)

mapCmd : (a -> b) -> Return model a reply -> Return model b reply

If you need to transform just the cmd in a Return, such as if you need to wrap a sub-modules msg type

loginModel
    |> Login.update subMsg
    |> mapCmd LoginMsg

mapReply : (Maybe a -> Maybe b) -> Return model msg a -> Return model msg b

Get

model : Return model msg reply -> model

Ideally you wouldnt have to deconstruct a Return, but if you need to, this function does it.

Return3.model (model, cmd, Nothing) == model

cmd : Return model msg reply -> Platform.Cmd.Cmd msg

Get the cmd of an already packed Return.

Return3.cmd (model, cmd, reply) == cmd

reply : Return model msg reply -> Maybe reply

Get the reply of an already packed Return, if it exists

Return3.reply (model, cmd, maybeReply) == maybeReply

Incorporate

incorp : (subModel -> Maybe reply -> model -> ( model, Platform.Cmd.Cmd msg )) -> model -> Return subModel msg reply -> ( model, Platform.Cmd.Cmd msg )

Returns contain a reply, and that reply needs to be handled much like a msg does in an update function.

loginModel
    |> Login.update loginMsg
    |> R3.mapCmd LoginMsg
    |> incorp handleLoginReply model


handleLoginReply : Login.Model -> Maybe Reply -> Model -> (Model, Cmd Msg)
handleLoginreply loginModel maybeReply model =
    case maybeReply of
        Nothing ->
            { model | page = Login loginModel }
                |> R2.withNoCmd

        Just (LoggedIn user) ->
            { model
                | page = Home Home.init
                , user = Just user
            }
                |> R2.withNoCmd