20-CS-4003-001 Organization of Programming Languages Fall 2018
Exceptions

Lambda calculus, Type theory, Formal semantics, Program analysis

Prev     Next     All lectures           Code

Built-in Exceptions

 ``` divBy num = map (num `div`) v1 = divBy 7 [1,2,3,4,5] v2 = divBy 7 [1,2,3,4,0,5,6,7] v3 = take 15 (map (\x -> 7 / x) [10,9..]) divBy1 _ [] = Just [] divBy1 _ (0:_) = Nothing divBy1 num (den:xs) = case divBy1 num xs of Nothing -> Nothing Just res -> Just ((num `div` den) : res) v4 = divBy1 7 [1,2,3,4,5] v5 = divBy1 7 [1,2,3,4,0,5,6,7] {- try divBy1 7 [1..] -} divBy2 num dens = map worker dens where worker 0 = Nothing worker x = Just (num `div` x) v6 = divBy2 7 [1,2,3,4,5] v7 = divBy2 7 [1,2,3,4,0,5,6,7] v8 = take 30 \$ divBy2 7 [10,9..] divBy3 _ [] = Right [] divBy3 _ (0:_) = Left "divBy3: divide by 0" divBy3 num (den:xs) = case divBy3 num xs of Left x -> Left x Right res -> Right ((num `div` den) : res) v9 = divBy3 7 [1,2,3,4,5] v10 = divBy3 7 [1,2,3,4,0,5,6,7] v11 = divBy3 7 [10,9..] divBy4 num dens = map worker dens where worker 0 = Right "Hah!!" worker x = Left (num `div` x) v12 = divBy4 7 [1,2,3,4,5] v13 = divBy4 7 [1,2,3,4,0,5,6,7] v14 = take 15 (divBy4 7 [12,11..]) ``` - Haskell provides built-in exceptions. Illustrated here is the DivideByZero exception which is in the class of ArithExceptions. The div operator is used to trigger that exception in these examples since the / operator's zero division is handled internally. The divBy function to the left divides a given number by all the numbers in a given list. The type signature of divBy is this: ``` divBy :: Integral a => a -> [a] -> [a] ``` Sample output: ```*Main> divBy 7 [1,2,3,4,5] [7,3,2,1,1] *Main> divBy 7 [1,2,3,4,0,5,6,7] [7,3,2,1,*** Exception: divide by zero *Main> take 20 \$ divBy 7 [1..] [7,3,2,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0] *Main> divBy 7 [10,9..] [0,0,0,1,1,1,1,2,3,7,*** Exception: divide by zero ``` In the second and fourth examples an exception was raised, terminating execution with a partial solution. Note that no exception is raised by the following: ```*Main> take 13 (map (\x -> 7 / x) [10,9..]) [0.7,0.77..,0.875,1.0,1.16..,1.4,1.75,2.33.., 3.5,7.0,Infinity,-7.0,-3.5] ``` This can be made to happen with div as well. The first attempt, divBy1, is not efficient since all results must be known and stored someplace just in case there is no Nothing to output (then the results are returned - otherwise Nothing is). Sample outputs are: ```*Main> divBy1 7 [1,2,3,4,5] Just [7,3,2,1,1] *Main> divBy1 7 [1,2,3,4,0,5,6,7] Nothing *Main> divBy1 7 [10,9..] Nothing ``` So, it's either all or nothing but it is preferred to have all the results with the Nothing occupying places where the divide-by-zero error occurs. The type signature for divBy1 is this: ```divBy1 :: a -> [a] -> Maybe [a] ``` but what is really required is what divBy2 provides: ```divBy2 :: a -> [a] -> [Maybe a] ``` Sample output is this: ```*Main> divBy2 7 [1,2,3,4,5] [Just 7,Just 3,Just 2,Just 1,Just 1] *Main> divBy2 7 [1,2,3,4,0,5,6,7] [Just 7,Just 3,Just 2,Just 1,Nothing, Just 1,Just 1,Just 1] *Main> take 13 \$ divBy2 7 [10,9..] [Just 0,Just 0,Just 0,Just 1,Just 1,Just 1,Just 1, Just 2,Just 3,Just 7,Nothing,Just (-7),Just (-4)] ``` A problem with Maybe Monad is that failure results in Nothing. That means no information is given about the failure. The Either Monad can be used to return such information. This is shown by divBy3 which has a type signature: ```divBy3 :: Integral t => t -> [t] -> Either [Char] [t] ``` Sample out is as follows: ```*Main> divBy3 7 [1,2,3,4,5] Right [7,3,2,1,1] *Main> divBy3 7 [1,2,3,4,0,5,6,7] Left "divBy3: division by 0 - no good" *Main> divBy3 7 [10,9..] Left "divBy3: division by 0 - no good" ``` The counterpart to divBy2 is divBy4 with type signature ```divBy4 :: Integral a => a -> [a] -> [Either a [Char]] ``` Sample output is as follows: ```*Main> divBy4 7 [1,2,3,4,5] [Left 7,Left 3,Left 2,Left 1,Left 1] *Main> divBy4 7 [1,2,3,4,0,5,6,7] [Left 7,Left 3,Left 2,Left 1,Right "Hah!!", Left 1,Left 1,Left 1] *Main> take 13 \$ divBy4 7 [12,11..] [Left 0,Left 0,Left 0,Left 0,Left 0,Left 1, Left 1,Left 1,Left 1,Left 2,Left 3,Left 7, Right "Hah!!"] ```