Expressive and composable error types

前端 未结 1 1605
执念已碎
执念已碎 2021-02-04 03:31

I am struggling with the best way to report errors in a set of functions that should compose nicely, in a library I\'m working on.

Concretely, I have functions that loo

1条回答
  •  醉话见心
    2021-02-04 04:07

    The Control.Monad.Exception library allows strongly typed exceptions to be used in non IO code. This allows functions to throw errors, and easily compose with functions that throw different errors. For example:

    {-# LANGUAGE RankNTypes, MultiParamTypeClasses, FunctionalDependencies #-}
    {-# LANGUAGE FlexibleInstances #-}
    import Prelude hiding (catch)
    import Control.Monad.Exception
    
    
    data FooException = FooException deriving (Show, Typeable)
    instance Exception FooException
    
    data BarErrors = BarErrors deriving (Show, Typeable)
    instance Exception BarErrors
    
    data BazErrors = BazErrors deriving (Show, Typeable)
    instance Exception BazErrors
    
    -- sample functions    
    foo :: (Throws FooException l) => a -> EM l a
    foo a = return a
    
    
    bar :: (Throws BarErrors l) => a -> EM l a
    bar _ = throw BarErrors
    
    baz :: (Throws BazErrors l) => a -> EM l a
    baz a = return a
    
    
    -- using all at once:
    
    allAtOnce :: (Throws FooException l, Throws BarErrors l, Throws BazErrors l) =>
                 a -> EM l String
    allAtOnce x = do
      _ <- foo x
      _ <- bar x
      _ <- baz x
      return "success!"
    
    -- now running the code, catching the exceptions:
    
    run :: a -> String
    run x = runEM $ allAtOnce x `catch` (\(_ :: FooException) -> return "foo failed")
            `catch` (\BarErrors -> return "bar failed")
            `catch` (\BazErrors -> return "baz failed")
    
    
    -- run 3 results in "bar failed"
    

    See also the papers Explicitly Typed Exceptions for Haskell and An Extensible Dynamically-Typed Hierarchy of Exceptions for more details on using this library.

    0 讨论(0)
提交回复
热议问题