I propose to introduce an additional type parameter for editors.
Currently, the type of editors is
Editor a. The type indicates the value an editor works on. Such value is given if the editor is created in update/view, but not in enter mode. Furthermore, an editor can either be in an empty/invalid state without producing a value or in a valid state producing a value.
I propose to extend the type to
Editor p a. The editor always gets additional parameter information of type
p, so also in enter mode. The second type parameter is the value the editors works on, basically the same way as it does currently.
I'll give two example to demonstrate thy this is necessary:
We can't really type an editor for choosing a single value with the current type. With a single value we have to use the type
Editor ([a], Int). The problem is that in enter mode there is no value, so we can't provide the list of options as input. As a workaround we have to use a type such as
Editor ([a], Maybe Int). Then we can use combinators to map enter mode to updating
(choices, Nothing), this is more or less how it works now. This is of course not very neat, as the editor will always have a value then, also in case nothing is chosen.
As second example consider something as the input field of google. You can type in things, but there is also a list of suggestions. This will never work reliably with a type
Editor ([String], String). At the moment you want to update the suggestions, you have no choice but to also set the value, the user is typing in, i.e.
(suggestions, curValue). The
curValue on the server may however be outdated and all characters the user typed in since the last edit event was processed will be removed.
Of course, this will make the editor combinators and usage more complicated, but I think we can restrict the complexity for cases the parameter is not required. I haven't though this out, but I think it should be possible to do something like this:
:: ParamEditor p a = ... :: Editor a :== ParamEditor () a
Then the type of the current combinators and options doesn't have to be changed. For instance, we can add a new constructor to
UpdateOption and leave the others as they are:
:: UpdateOption a b = E.v: UpdateAs (a -> v) (a -> v -> b) & iTask v | E.v: UpdateUsing (a -> v) (a -> v -> b) (Editor v) & iTask v | E.v: UpdateSharedAs (a -> v) (a -> v -> b) (v -> v -> v) & iTask v | E.p v: UpdateUsingParamEditor (a -> (p, v)) (a -> v -> b) (ParamEditor p v) & iTask v