The long version
The Formless component has a lot of type parameters. Here’s the query type:
data Query parentQuery childQuery childSlot userForm formOutput m a = ...
The first three types are all used so that you can embed whatever components you’d like into a form. The m parameter specifies the monad Formless runs in, which can be whatever you want, and there’s the standard a for Halogen queries. Let’s look at a simpler type synonym:
type Query' userForm formOutput m a = ...
-
userForm is the form type the user has specified and passed to Formless. It might be { password1, password2, email }, for example.
-
formOutput is the resulting type the form is meant to produce. It might be { email, password }, for example, collapsing the password fields.
Formless accepts a function, submitter, which is essentially a function userForm -> m formOutput. The entire point of this function is that it will turn the form type into the output type before returning that to the end user in a message:
data Message formOutput
= Submitted formOutput
...
How things work right now
In the current design, the user must pass a submitter function as input, and Formless will apply it before returning the output in a message when the user submits a form.
This doesn’t save you much work – you had to write the function either way, and you could have just applied it when you received the Submitted message rather than it being applied before the message is sent. It’s the different between (Submitted userForm) and (Submitted formOutput).
For this marginal benefit, Formless picks up an extra type parameter, formOutput. Worse, this type parameter can get confusing if, say, you’re doing a computation that could produce an error (now it’s Either Error FormOutput) or multiple types, depending (now it’s Either Form1 Form2), or you still have to do a transformation afterwards.
That said, the nice thing about this type parameter is that it’s quite informative – it’s essentially saying “This form will produce this type.” It’s a particularly nice parameter:
Formless.Query pq cq cs MyForm User m a
-- vs.
Formless.Query pq cq cs MyForm m a
As it stands, I’m conflicted as to which of these is better. You could just write UserForm, assume that it will parse to a User, and call it a day. It might be frustrating to have to carry the extra type everywhere and it makes the component more intimidating type-signature-wise.
But it may also be frustrating to have to look in your code to remember what the form parses into on a successful submission. Much easier to glance at the type and see there.
To restate the question:
given that the type parameter adds almost no functionality to a component using it, but it does add some possibly-useful information at a glance, is it worth the extra complexity of carrying it around?