Interesting! I’ve been using the same approach at work for validation, and it’s been really nice. I like the simplicity of only storing raw user input in the model, and validating as needed, with just a few helper functions.
For pipelining, I’ve an awkwardly named
applyOrAccumulate : Result x a -> Result (List x) (a -> b) -> Result (List x) b
function to use as you described.
formToData : form -> Result (List error) Data
formToData form =
Ok Data
|> applyOrAccumulate (form.email |> validateEmailString)
|> applyOrAccumulate ...
Looking forward to seeing this kind of approach as a package.