Here's an example (first in Haskell then in Go), lets say you have some types/functions:
then you can make
mkValidUser :: String -> Int -> Possible User
mkValidUser name age = do
validatedName ← validateName name
validatedAge ← validateAge age
pure $ User validatedName validatedAge
for some reason <- in lemmy shows up as <-
inside code blocks, so I used the left arrow unicode in the above instead
in Go you'd have these
Possible
type alias, Go can't do generic type aliases yet, there's an open issue for it)and with them you'd make:
func mkValidUser(name string, age int) (*User, error) {
validatedName, err = validateName(name)
if err != nil {
return nil, err
}
validatedAge, err = validateAge(age)
if err != nil {
return nil, err
}
return User(Name: validatedName, Age: validatedAge), nil
}
In the Haskell, the fact that Either
is a monad is saving you from a lot of boilerplate. You don't have to explicitly handle the Left
/error case, if any of the Either
s end up being a Left
value then it'll correctly "short-circuit" and the function will evaluate to that Left
value.
Without using the fact that it's a functor/monad (e.g you have no access to fmap/>>=/do syntax), you'd end up with code that has a similar amount of boilerplate to the Go code (notice we have to handle each Left
case now):
mkValidUser :: String -> Int -> Possible User
mkValidUser name age =
case (validatedName name, validateAge age) of
(Left nameErr, _) => Left nameErr
(_, Left ageErr) => Left ageErr
(Right validatedName, Right validatedAge) =>
Right $ User validatedName validatedAge