## Thursday 1 October 2009

### Dealing with Partial Functions

Functions can be either total (e.g. fully defined for all possible input values) or partial. Handling partial functions can be painful, for example if you pass an empty list to `head` then it'll terminate the program with an exception.

Partial functions are usually handled by either pattern matching being used to exclude cases where the function isn't defined e.g.

`  foo [] = 33      -- not safe to call head  foo xs = head xs -- safe to call head`

Or using `Maybe` to indicate (via the type system) that the function might not return a value. The first exercise of chapter 4 of Real World Haskell asks you to rewrite some of the partial list functions so that they never fail.

`  safeHead :: [a] -> Maybe a  safeHead [] = Nothing  safeHead (x:_) = Just x  safeTail :: [a] -> Maybe [a]  safeTail [] = Nothing  safeTail (_:xs) = Just xs  safeLast :: [a] -> Maybe a  safeLast [] = Nothing  safeLast (y:[]) = Just y  safeLast (_:xs) = safeLast xs  safeInit :: [a] -> Maybe [a]  safeInit [] = Nothing  safeInit (x:[]) = Just []  safeInit (x:xs) = Just (x : fromJust(safeInit xs))`

In order to be thorough, I thought I'd explore HUnit a bit more and write a few tests. The funny "~:" and "~=?" are just syntactic sugar for writing assertions. One area that confused me was the need to specify the type explicitly on the functions for undefined values. I'm not entirely sure why this has to be done...

`  testSafeHead = test [ "Safe head non-empty" ~: Just 1 ~=? safeHead [1]                      , "Safe head null" ~: Nothing ~=? (safeHead [] :: Maybe Int) ]    testSafeTail = test [ "Safe tail empty" ~: Just [] ~=? safeTail [1]                      , "Safe tail value" ~: Just [1] ~=? safeTail [2,1]                      , "Safe tail nothing" ~: Nothing ~=? (safeTail [] :: Maybe [Int]) ]  testSafeLast = test [ "Safe last empty" ~: Nothing ~=? (safeLast [] :: Maybe Int)                      , "Safe last 1 element" ~: Just 1 ~=? safeLast [1]                      , "Safe last n element" ~: Just 1 ~=? safeLast [3,2,1] ]  testSafeInit = test [ "Safe Init empty" ~: Nothing ~=? (safeInit [] :: Maybe [Int])                      , "Safe Init singleton" ~: Just [] ~=? safeInit [1]                      , "Safe Init list" ~: Just [1,2] ~=? safeInit [1,2,3] ]  tests = TestList [TestLabel "safeHead" testSafeHead                   ,TestLabel "safeTail" testSafeTail                   ,TestLabel "safeLast" testSafeLast                   ,TestLabel "safeInit" testSafeInit]`

You can run these tests within ghci with
`  *Main> runTestTT tests  Cases: 11  Tried: 11  Errors: 0  Failures: 0  Counts {cases = 11, tried = 11, errors = 0, failures = 0}`

I think these tests would have been better written with QuickCheck where I could have compared them with the non-safe versions. But this'll do for now!