Kivételkezelés

Kivételkezelés

A kivételkezelés a ⊥ kezelése a végrehajtás szintjén.

Mikor használjuk?

-- import Control.Exception  -- base csomag

Kiértékelésből származó kivételek

-- data PatternMatchFail = PatternMatchFail String
-- data ErrorCall = ErrorCall String
-- data AssertionFailed  = AssertionFailed String
-- data NonTermination = NonTermination

Kiértékelésből származó kivételek (2)

-- data ArithException
--    = Overflow
--    | Underflow
--    | LossOfPrecision
--    | DivideByZero
--    | Denormal
-- data ArrayException
--    = IndexOutOfBounds String
--    | UndefinedElement String

Kiértékelésből származó kivételek (3)

-- data NoMethodError = NoMethodError String
-- data RecConError = RecConError String
-- data RecSelError = RecSelError String
-- data RecUpdError = RecUpdError String

Végrehajtásból származó kivételek

-- data IOException
-- data AsyncException
--    = StackOverflow
--    | HeapOverflow
--    | ThreadKilled
--    | UserInterrupt  -- Ctrl+C

Végrehajtásból származó kivételek (2)

Nincs több futó szál:

-- data Deadlock = Deadlock

A thread blokkolt egy MVar-on, de más referencia nincs az MVar-ra:

-- data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar
-- data NestedAtomically = NestedAtomically
-- data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM

Tetszőleges kivétel

-- data SomeException = forall e . Exception e => SomeException e    
-- class (Typeable e, Show e) => Exception e  where
import ActiveHs.Base
import MyPrelude
import Prelude hiding (length)
--    toException   :: e -> SomeException
--    fromException :: SomeException -> Maybe e
-- instance Exception ArithException
-- instance Exception ErrorCall
-- ...

A két fő művelet

-- throwIO :: Exception e => e    -> IO a
-- try     :: Exception e => IO a -> IO (Either e a)

Elméleti modell (közelítőleges):

-- data Expr a = Bottom Exception | Data a
-- throwIO e = Bottom e
-- try (Bottom e) = Left e
-- try (Data a)   = Right (Data a)

Származtatott műveletek

Ismerős forma:

-- catch :: Exception e => IO a -> (e -> IO a) -> IO a
-- catch a f = do
--    x <- try a
--    case x of
--        Left e  -> f e
--        Rigth a -> return a

Kiértékelés közbeni kivétel dobás

Veszélytelen, de elvi okok miatt ne használjuk:

-- throw :: Exception e => e -> a

Nagyon hasznos:

-- throwTo :: Exception e => ThreadId -> e -> IO ()

Példa:

-- killThread t = throwTo t ThreadKilled