On Wednesday, February 22, 2017 at 8:41:41 PM UTC, Brian Marick wrote: > > I’m comfortable with sum and product types by themselves, but I flounder > when trying to combine them. Should I model the problem as a sum type > inside a record? as records in a sum type?
The way I am approaching it at the moment is as follows: 1. Go through all the fields needed to implement the module or application and pick out the ones that are always needed. Put those in the Model record (at the top level) - the main product. 2. Figure out a state diagram describing the behavior of your UI. I find this is tending to align very well with one state for each element of the UI that can change. For example, something shown or hidden, or something shown in one state or another. Turn the state diagram into a Type - the sum. 3. Group the remaining fields up depending on the situations where they are needed. These groupings will not necessary be 1:1 with the states, it is common for some groupings to be used in many states For example, I need the state for the menu toggle button to be available whether the menu itself is visible or not. Each group will be given a type alias as a record - these form a set of little products that are non-overlapping. They should definitely be non-overlapping. Once this is in place, I start writing the view and update functions - in terms of the little products of fields that they need to work with to update some part of the model, or render some part of the view. Then I use some functions I wrote around the state machine to select when to apply those functions - in a particular state or not, when a particular little product is available. I find this extra layer of flexibility that composing the states out of groupings of fields is very useful when it comes to changing the model. For example, one time I realized I needed to render something in the view, in a particular state that I had forgotten to include. The view function for it was written in terms of the little product needed to render that view - so when I added that product to the particular state, everything else just fell into place. I've created a Gist with an example model in it, and the boiler-plate functions I am using with these state machines. https://gist.github.com/rupertlssmith/c948f304ce0a99cd7ba9d6b6a061251a The model there is: type alias Model = { mode : Mode , menu : Menu } and I only listed out the 'Mode' state machine. 'Menu' is an independent state machine and it is implemented in another module. So it is an example of a thing that is always needs to be available in the Model along-side the state machine for this particular model. I agree with what you are saying about how refactoring can be a pain when you did not get the model right the first time and require very extensive changes. I am finding that this pattern of making the Model a product of sums of little products, is working quite flexibly. Particularly when you tend to write functions in terms of the little products re-factoring is more painless. Choosing how you divide stuff up into the little products is very similar to data modelling in OO languages. -- 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.
