There are N animals to display simultaneously. Each animal can be displayed in one of three ways: compactly (key info only); expanded (all info), and editable. Each animal is independent - for example, the user can be editing two animals at once.
This could be modeled with a single Animal record with a Display field that's Compact | Expanded | Editable and a Maybe FormValues field. Or, as I have it now:
type AnimalDisplay
= Compact
| Expanded
| Editable ChangingAnimalValues
type alias DisplayedAnimal =
{ persistent : PersistentAnimal
, display : AnimalDisplay
}The issue was not so much this representation as the messages, which were of this form for, say, a text field:
Events.onInput (ChangeNameCharacters animal.id)(The animals are stored in a Dict from id to DisplayedAnimal.)
To navigate from the id to the field that needs to change, you have to pass through union types. We know that the ChangeNameCharacters will only ever be sent to an Editable animal, but the compiler doesn't. This is annoying.
I'm thinking that the solution is that for the logic to be invoked in editableAnimalView in the form of some function that does the update (on the "leaf" object the typechecker is at this point sure I have) and yields a ReplaceAnimal Msg. Something like:
Events.onInput (produceName animal)
...
produceName animal string =
let
-- using lenses for `update-in` operations
newAnimal = animal_changingName.set string animal
in
ReplaceAnimal animal.id newAnimal