Most examples for Haskell generics do small bits of computation recursively around the :+: and :*: types/constructors. I seem to be solving a problem where this may not work out.
I'm trying to write a generic validation function that takes any two records having the same shape and validates each field in recordA against a validation function defined in recordB to return an error record of the same shape OR recordA itself.
Example:
-- Some type synonyms for better readability
type Name = Text
type Age = Int
type Email = Text
type GeneralError = Text
type FieldError = Text
-- a polymorphic record to help preserve the shape of various records
data User n a e = User {name :: n, age :: a, email :: e}
-- the incoming value which has been parsed into the correct type
-- but still needs various values to be validated, eg length, format, etc
type UserInput = User Name Age Email
-- specifies the exact errors for each field
type UserError = User [FieldError] [FieldError] [FieldError]
-- specifies how to validate each field. the validator is being passed
-- the complete record along with the specific field to allow
-- validations that depends on the value of another field
type UserValidator = User
(UserInput -> Name -> Either ([GeneralError], [FieldError]) Name)
(UserInput -> Age -> Either ([GeneralError], [FieldError]) Age)
(UserInput -> Email -> Either ([GeneralError], [FieldError]) Email)
let (validationResult :: Either ([GeneralError], UserError) UserInput)
= genericValidation (i :: UserInput) (v :: UserValidator)
Now, the reason why doing this recursively around :*: might not work is, that one needs to look at the result of every validation function and then decide if the return value should be a Left ([GeneralError], UserError) or a Right UserInput. We cannot evaluate to a Left value on the first validation function that fails.
Is there any way to write this genericValidation function using Haskell generics?