Haskell Safe Results
Safe results are return values that show whether a step succeeded or failed. Maybe and Either are two safe results that carry different amounts of detail.
Maybe fits a missing value with no reason
The findAge function returns Nothing for an unknown name. The caller learns only that no age was found.
findAge :: String -> Maybe Int
findAge "Ana" = Just 31
findAge _ = Nothing
main :: IO ()
main = print (findAge "Ben")Either keeps the reason
The validateAge function returns Left with a message for an age below 18. The message tells the caller why the check failed.
validateAge :: Int -> Either String Int
validateAge age
| age < 18 = Left "Too young"
| otherwise = Right age
main :: IO ()
main = print (validateAge 15)A second checked step divides safely
The dividePoints function returns Left when the game count is 0. For a game count of 4, it returns the points per game inside Right.
dividePoints :: Int -> Int -> Either String Int
dividePoints _ 0 = Left "Games cannot be zero"
dividePoints points games = Right (div points games)
main :: IO ()
main = print (dividePoints 100 4)Example
validateAge :: Int -> Either String Int
validateAge age
| age < 18 = Left "Too young"
| otherwise = Right age
dividePoints :: Int -> Int -> Either String Int
dividePoints _ 0 = Left "Games cannot be zero"
dividePoints points games = Right (div points games)
playerAverage :: Int -> Int -> Int -> Either String Int
playerAverage age points games =
case validateAge age of
Left msg -> Left msg
Right _ ->
case dividePoints points games of
Left msg -> Left msg
Right avg -> Right avg
main :: IO ()
main = print (playerAverage 20 90 3)Key points
- Maybe choice: use Maybe when the caller only needs to know that a value is missing.
- Either choice: use Either when the caller needs to know why a step failed.
- Checked step: a step that returns an Either value instead of an unchecked result.
- Pipeline: a chain of checked steps where one result feeds the next step.
- Case combining: a case reads each Either result and decides the next step.
In this example, playerAverage first runs validateAge on 20 and gets a Right value. It then runs dividePoints on 90 points and 3 games, which returns Right 30. The main action prints that final Right value.
Note
Haskell code in this style reports failure by returning a value, not by throwing an error.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
When should a function choose Either instead of Maybe?