Professional Documents
Culture Documents
Explicitly Typed Exceptions For Haskell (PADL'10)
Explicitly Typed Exceptions For Haskell (PADL'10)
PADL 2010
Checked Exceptions
• automatically documented
Checked Exceptions
• automatically documented
* - http://www.artima.com/intv/handcuffs.html
Exceptions in Haskell
EM
Yes Yes Yes Yes Yes!
monad
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
return = Right
return = Right
return = Right
return = Right
return = Right
return = Right
throw = Left
return = Right
José Iborra Universidad Politécnica de Valencia
throw = Left
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
throw = Left
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
throw = Left
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Checked
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• User extensible
• User extensible
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• User extensible
• Explicit ✓
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving Show
• Explicit
• Explicit
• Explicit
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving (Show,Typeable)
instance Exception DivByZero
data Expr = Add Expr Expr | Div Expr Expr | Val Double
data DivByZero = DivByZero deriving (Show,Typeable)
instance Exception DivByZero
runEM :: EM l x -> x
runEM (EM (Right x)) = x
|M | = m |N | = n |M | = m |N | = n
|M >>= N | = m ∪ n |if H then M else N | = m ∪ n
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
|M | = m |N | = n |M | = m |N | = n
|M >>= N | = m ∪ n |if H then M else N | = m ∪ n
>>=EM :: EM l a -> (a -> EM l b) -> EM l b
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
|M | = m |N | = n |M | = m |N | = n
|M >>= N | = m ∪ n |if H then M else N | = m ∪ n
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
This is not the most
instance Throws e (Caught e l) general type
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Implementing Catch
|C| = c |H| = h
|catch C (λe → H)| = (c \ {e}) ∪ h
data Caught e l
instance Throws e (Caught e l)
instance Throws e l => Throws e (Caught e1 l)
Running EM computations
• Checked version demanding that no exceptions leak:
runEM :: EM l a -> a
runEM (EM (Right x)) = x
Running EM computations
• Unchecked version accepting computations which may
raise any exception
data Any
instance Throws e Any
Running EM computations
• Unchecked version accepting computations which may
raise any exception
Running EM computations
• Unchecked version accepting computations which may
raise any exception
data Any
instance Throws e Any
Running EM computations
• Selectively turning exceptions into unchecked exceptions
Running EM computations
• Selectively turning exceptions into unchecked exceptions
run :: ...