Skip to content

Latest commit

 

History

History
84 lines (62 loc) · 2.26 KB

25.md

File metadata and controls

84 lines (62 loc) · 2.26 KB

Revisiting Maybe

In the previous lectures we saw the >> and >>= operators and the return function used with IO. It turns out that not only IO but a lot of other types with the same form support these operators.

Let's have a look at the type of these operators in case of the IO type.

(>>=) :: IO a -> (a -> IO b) -> IO b
(>>)  :: IO a -> IO b -> IO b
return :: a -> IO a

If we replace IO with Maybe, we get the following results.

(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
(>>)  :: Maybe a -> Maybe b -> Maybe b
return :: a -> Maybe a

The >> operator is not that interesting. What about the >>= operator? Maybe is an ideal type to represent actions that might fail. The following pattern is used frequently in imperative programming.

def validateAges(listAsString):
  intList = parseStringList(listAsString)
  if not intList:
    return None

  ret = mean(intList) # might raise exception

  if ret > 400:
    return None

  if ret < 0:
    return None

  return ret

The previous code looks like this in Haskell:

import Text.Read

safeMean :: [Int] -> Maybe Int
safeMean [] = Nothing
safeMean lst = Just ((sum lst) `div` (length lst))

data Age = Age Int deriving (Eq, Show)

toAge :: Int -> Maybe Age
toAge age
  | age < 0 = Nothing
  | age > 400 = Nothing
  | otherwise = Just (Age age)

validateMeanAge :: String -> Maybe Age
validateMeanAge str = case (readMaybe str) :: Maybe [Int] of
                        Nothing -> Nothing
                        Just lst -> case safeMean lst of
                                      Nothing -> Nothing
                                      Just mean -> toAge mean

This looks terrible. Although if you have a look at the type of each case expression an interesting pattern emerges. Maybe a -> (a -> Maybe b) -> Maybe b which is exactly the same as the type of >>=.

validateMeanAge :: String -> Maybe Age
validateMeanAge str = (readMaybe str) >>= safeMean >>= toAge

This is beautiful. I can not imagine a more concise description of the problem with the tools that we have now.

Exercise

  • Since all of the necessary operators are implemented for Maybe, you can use do notation. Rewrite validateMeanAge using do notation.