Thanks! So let's start by talking about Slider for a sec.

      SliderMsg (Slider.ChangeValue newSpeed) ->
        { model | profile = newInternal, shared = Trip.setAverageSpeed model
.shared newSpeed }

Because this code compiles, and it only covers the ChangeValue constructor, 
then assuming speed is an Int, I can infer that Slider's Msg looks like 
this:

type Msg = ChangeValue Int

A good question at this point is: *how much of Slider's state must be 
synchronized *with other state in the application?

For example, if Slider had some sort of visual flourish like "every time 
you drag it, it changes color," that state would not need any 
synchronization with other parts of the app. The slider would change color 
when you dragged it, and the rest of the application would neither know nor 
care.

The Slider's value is not independent like this. If you put a slider on a 
page and its value changes, but no other code ever finds out that its value 
changed, then the slider is useless! Its value needs to be synchronized 
with other state in order to be useful.

Since Slider has no other state besides this value, then Slider's state is 
*100% 
synchronized* with other state. In a case like this, you have two options 
for keeping it in synchronized:

1. Give Slider its own Msg, and translate between its Msg and its caller's 
Msg
2. Do not give Slider its own Msg, just have its view accept a Msg 
*constructor* as an argument.

The second option is simpler. Here's how that would look:


viewSlider : (value -> msg) -> value -> Html msg


Now we can change Profile's Msg to this:

type Msg =
  WaypointConfMsg Int WaypointConf.Msg
  | *SetSpeed Int*


...and render the slider like this:

viewSlider SetSpeed currentSpeed

So now Slider no longer has its own Msg, it just says "hey caller, tell me 
how to wrap my values in your Msg type, whatever that might be, and we're 
cool." Now instead of Slider being a Model, a Msg, an update, and a 
view...it's just a view! :)

Let's look at Waypoint next:

WaypointConfMsg idx msg' ->
        case msg' of
          WaypointConf.ChangeDateOrTime _ ->
            { model | profile = newInternal, shared = Trip.changeOpDate 
model.shared idx <| getDate idx model newInternal }
          WaypointConf.SameDateAndTime _ ->
            { model | profile = newInternal }

Like Slider, its state is still *100% synchronized*, meaning it also 
doesn't need its own Msg. We can convert Waypoint into a view function 
(which accepts a "here's how to wrap things as a Msg" function just like 
Slider did—or maybe two of those functions, since there are two things 
Waypoint can change), at which point we no longer need a Waypoint Msg, 
Model, or update. Only a view.

Finally, since Profile only has Waypoint and Slider inside it, and since 
Profile has no independent state to track either, we can give it exactly 
the same treatment as what we did for Waypoint and Slider.

To summarize how I'd recommend organizing things:


*Current*

WaypointConf - Model, Msg, update, view
Slider - Model, Msg, update, view

Profile - Model, Msg, update, view

App - Model, Msg, update, view


*Proposed*

WaypointConf - view
Slider - view
Profile - view

App - Model, Msg, update, view


Hope that helps! :)

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to