I have a Haskell function which takes user input and another function which validates this input. Of course, the validation could fail, in which case I would like to return an error message giving some feedback on what was done incorrectly.
I know that there are many ways that I could do this. After the little experience I have, it seems like the best way is to use Either String a
. What is throwing me off is that I don't care about the a
. Either it fails and I would like to store more information, or it succeeds. The a
is wasted.
Is using Maybe String
an acceptable way to store an error message? It feels backwards to me, but completely ignoring the value in the right of an Either
feels pretty bad too. What is canonical here?
I encourage the use of Except String ()
(or Either String ()
) over Maybe String
, for a few reasons:
String
is a phone number, you might want to return the area code, first, and second parts of the number, giving a validation type like String -> Except String (Int, Int, Int)
or similar. Making validators that don't return anything interesting have type Foo -> Except String ()
makes them just a special case of this pattern -- and therefore easier to fit together.Continuing the "fit together" part, you may later find that you want to construct one big validator out of smaller ones. Perhaps you have a validator that checks that a person has specified a valid age and birth date, and want to build a validator out of this that also checks that the age is about right for the birth date. The Monad
instance for Either
will help here; for example:
validatePerson p now = do
age <- validateAge p
date <- validateBirthdate p
validateMatchingAgeAndDate age date now
Or perhaps there are two ways for some value to validate properly and you want to allow either. Then bigValidator v = option1 v <|> option2 v
is a cheap and cheerful way to combine the two ways of validating.
As a side benefit, these methods of combining existing validators to make bigger ones will be instantly recognizable to other Haskellers.
There is a very strong convention that Nothing
is a failure. Using the opposite convention is not a problem, necessarily, but could be confusing to other contributors and potentially to yourself far in the future.