Search code examples
architecturemessageelmreducers

Dividing main update function based on sub-messages


I am trying to separate my top level messages to sub messages and hence i did:

type GeneratorMsg
    = BoidsGenerated (List Boid)
    | ColoursGenerated (List Color)


type Msg
    = Tick Time
    | UpdateWorld Window.Size
    | GeneratorMsg

However, in my main update function when I use the BoidsGenerated message Elm thinks that it is of type GeneratorMsg which is correct. In the same time though - in my mind -, it is of type Msg.

Is there a way to be able to handle Msg and GeneratorMsg interchangeably? Basically, i want to split my update function to smaller functions but I want everything that has to do with generated stuff to be handled by 1 separate function. Then that function will have cases for BoidsGenerated and ColoursGenerated msgs. --- thanks


Solution

  • What you have here is a collision of names. You have a type called GeneratorMsg as well as a constructor called GeneratorMsg of a different type (Msg).

    The way you have defined the GeneratorMsg constructor of Msg, it is parameterless and contains no payload of information. You need to define a parameter to carry the GeneratorMsg value:

    type Msg
        = Tick Time
        | UpdateWorld Window.Size
        | GeneratorMsg GeneratorMsg
    

    You could then handle the updates in a separate function but you'll have to Cmd.map to wrap up the GeneratorMsg into a Msg value:

    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            GeneratorMsg gmsg ->
                let
                    ( gmodel, newMsg ) =
                        updateGenerator gmsg model
                in
                    (gmodel, Cmd.map GeneratorMsg newMsg)
    
            _ ->
                ...
    
    
    updateGenerator : GeneratorMsg -> Model -> ( Model, Cmd GeneratorMsg )
    updateGenerator gmsg model =
        case gmsg of
            BoidsGenerated boids ->
                ...
    
            ColoursGenerated colours ->
                ...