variant-1.0.2: Variant and EADT
Safe HaskellNone
LanguageHaskell2010

Data.Variant.Excepts

Contents

Description

Multi-exception monad transformer

Just like ExceptT e m a from the transformers package wraps an Either e a value, Excepts wraps a VEither value (see Data.Variant.VEither) and provides standard do-notation for computations that can fail with multiple error types.

Example

import Data.Variant.Excepts

import Prelude hiding (head,lookup)
import qualified Prelude
import Text.Read

data ParseError = ParseError deriving Show

parse :: String -> Excepts [ParseError] IO Integer
parse s = case readMaybe s of
   Just i  -> pure i
   Nothing -> throwE ParseError


data HeadError = ListWasEmpty deriving Show

head :: [a] -> Excepts [HeadError] IO a
head []    = throwE ListWasEmpty
head (x:_) = pure x

data LookupError k = KeyWasNotPresent k deriving Show

lookup :: Eq k => k -> [(k,v)] -> Excepts [LookupError k] IO v
lookup k vs = case Prelude.lookup k vs of
   Just v  -> pure v
   Nothing -> throwE (KeyWasNotPresent k)


foo :: String -> Excepts [ParseError, LookupError Char, HeadError] IO Integer
foo str = do
   c <- liftE $ head str
   r <- liftE $ lookup c codeMap
   liftE $ parse (r ++ tail str)

   where
      codeMap :: [(Char, String)]
      codeMap = [ ('x', "0x")
                , ('d', "")
                ]

Test:

> runE (foo "d10")
VRight 10

> runE (foo "x10")
VRight 16

> runE (foo "u10")
VLeft KeyWasNotPresent 'u'

> runE (foo "")
VLeft ListWasEmpty

> runE (foo "d10X")
VLeft ParseError

Exceptions can be caught with catchE:

> runE (foo "" `catchE` (\ListWasEmpty -> successE 42)
>    :: Excepts [ParseError,LookupError Char] IO Integer)
VRight 42
Synopsis

Documentation

newtype Excepts (es :: [Type]) (m :: Type -> Type) a Source #

Constructors

Excepts (m (VEither es a)) 

Instances

Instances details
MonadReader r m => MonadReader r (Excepts e m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

ask :: Excepts e m r #

local :: (r -> r) -> Excepts e m a -> Excepts e m a #

reader :: (r -> a) -> Excepts e m a #

MonadTrans (Excepts e) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

lift :: Monad m => m a -> Excepts e m a #

MonadFail m => MonadFail (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

fail :: String -> Excepts es m a #

MonadIO m => MonadIO (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

liftIO :: IO a -> Excepts es m a #

Foldable m => Foldable (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

fold :: Monoid m0 => Excepts es m m0 -> m0 #

foldMap :: Monoid m0 => (a -> m0) -> Excepts es m a -> m0 #

foldMap' :: Monoid m0 => (a -> m0) -> Excepts es m a -> m0 #

foldr :: (a -> b -> b) -> b -> Excepts es m a -> b #

foldr' :: (a -> b -> b) -> b -> Excepts es m a -> b #

foldl :: (b -> a -> b) -> b -> Excepts es m a -> b #

foldl' :: (b -> a -> b) -> b -> Excepts es m a -> b #

foldr1 :: (a -> a -> a) -> Excepts es m a -> a #

foldl1 :: (a -> a -> a) -> Excepts es m a -> a #

toList :: Excepts es m a -> [a] #

null :: Excepts es m a -> Bool #

length :: Excepts es m a -> Int #

elem :: Eq a => a -> Excepts es m a -> Bool #

maximum :: Ord a => Excepts es m a -> a #

minimum :: Ord a => Excepts es m a -> a #

sum :: Num a => Excepts es m a -> a #

product :: Num a => Excepts es m a -> a #

Traversable m => Traversable (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

traverse :: Applicative f => (a -> f b) -> Excepts es m a -> f (Excepts es m b) #

sequenceA :: Applicative f => Excepts es m (f a) -> f (Excepts es m a) #

mapM :: Monad m0 => (a -> m0 b) -> Excepts es m a -> m0 (Excepts es m b) #

sequence :: Monad m0 => Excepts es m (m0 a) -> m0 (Excepts es m a) #

(Functor m, Monad m) => Applicative (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

pure :: a -> Excepts es m a #

(<*>) :: Excepts es m (a -> b) -> Excepts es m a -> Excepts es m b #

liftA2 :: (a -> b -> c) -> Excepts es m a -> Excepts es m b -> Excepts es m c #

(*>) :: Excepts es m a -> Excepts es m b -> Excepts es m b #

(<*) :: Excepts es m a -> Excepts es m b -> Excepts es m a #

Functor m => Functor (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

fmap :: (a -> b) -> Excepts es m a -> Excepts es m b #

(<$) :: a -> Excepts es m b -> Excepts es m a #

Monad m => Monad (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

(>>=) :: Excepts es m a -> (a -> Excepts es m b) -> Excepts es m b #

(>>) :: Excepts es m a -> Excepts es m b -> Excepts es m b #

return :: a -> Excepts es m a #

MonadCatch m => MonadCatch (Excepts e m) Source #

Catches exceptions from the base monad.

Instance details

Defined in Data.Variant.Excepts

Methods

catch :: (HasCallStack, Exception e0) => Excepts e m a -> (e0 -> Excepts e m a) -> Excepts e m a #

MonadMask m => MonadMask (Excepts e m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

mask :: HasCallStack => ((forall a. Excepts e m a -> Excepts e m a) -> Excepts e m b) -> Excepts e m b #

uninterruptibleMask :: HasCallStack => ((forall a. Excepts e m a -> Excepts e m a) -> Excepts e m b) -> Excepts e m b #

generalBracket :: HasCallStack => Excepts e m a -> (a -> ExitCase b -> Excepts e m c) -> (a -> Excepts e m b) -> Excepts e m (b, c) #

MonadThrow m => MonadThrow (Excepts e m) Source #

Throws exceptions into the base monad.

Instance details

Defined in Data.Variant.Excepts

Methods

throwM :: (HasCallStack, Exception e0) => e0 -> Excepts e m a #

(MonadCatch m, MonadUnliftIO m, Exception (V es)) => MonadUnliftIO (Excepts es m) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

withRunInIO :: ((forall a. Excepts es m a -> IO a) -> IO b) -> Excepts es m b #

Show (m (VEither es a)) => Show (Excepts es m a) Source # 
Instance details

Defined in Data.Variant.Excepts

Methods

showsPrec :: Int -> Excepts es m a -> ShowS #

show :: Excepts es m a -> String #

showList :: [Excepts es m a] -> ShowS #

runE :: forall (es :: [Type]) a m. Excepts es m a -> m (VEither es a) Source #

Run an Excepts

runE_ :: forall (es :: [Type]) a m. Functor m => Excepts es m a -> m () Source #

Run an Excepts, discard the result value

liftE :: forall (es' :: [Type]) (es :: [Type]) a (m :: Type -> Type). (Monad m, VEitherLift es es') => Excepts es m a -> Excepts es' m a Source #

Lift a Excepts into another

appendE :: forall (ns :: [Type]) (es :: [Type]) a (m :: Type -> Type). Monad m => Excepts es m a -> Excepts (Concat es ns) m a Source #

Append errors to an Excepts

prependE :: forall (ns :: [Type]) (es :: [Type]) a (m :: Type -> Type). (Monad m, KnownNat (Length ns)) => Excepts es m a -> Excepts (Concat ns es) m a Source #

Prepend errors to an Excepts

failureE :: forall e a (m :: Type -> Type). Monad m => e -> Excepts '[e] m a Source #

Signal an exception value e.

successE :: forall a (m :: Type -> Type). Monad m => a -> Excepts ('[] :: [Type]) m a Source #

Signal a success

throwE :: forall e (es :: [Type]) a (m :: Type -> Type). (Monad m, e :< es) => e -> Excepts es m a Source #

Signal an exception value e.

throwSomeE :: forall (es' :: [Type]) (es :: [Type]) a (m :: Type -> Type). (Monad m, LiftVariant es' es) => V es' -> Excepts es m a Source #

Throw some exception

catchE :: forall e (es' :: [Type]) (es'' :: [Type]) (es :: [Type]) a (m :: Type -> Type). (Monad m, e :< es, LiftVariant (Remove e es) es', LiftVariant es'' es') => (e -> Excepts es'' m a) -> Excepts es m a -> Excepts es' m a Source #

Handle an exception. Lift both normal and exceptional flows into the result flow

catchEvalE :: forall m (es :: [Type]) a. Monad m => (V es -> m a) -> Excepts es m a -> m a Source #

Evaluate a Excepts. Use the provided function to handle error cases.

evalE :: Monad m => Excepts ('[] :: [Type]) m a -> m a Source #

Convert a flow without error into a value

onE_ :: forall m (es :: [Type]) a. Monad m => m () -> Excepts es m a -> Excepts es m a Source #

Do something in case of error

onE :: forall m (es :: [Type]) a. Monad m => (V es -> m ()) -> Excepts es m a -> Excepts es m a Source #

Do something in case of error

finallyE :: forall m (es :: [Type]) a. Monad m => m () -> Excepts es m a -> Excepts es m a Source #

Finally for Excepts

injectExcepts :: forall (es :: [Type]) a (m :: Type -> Type). Monad m => Excepts es m a -> Excepts es m (VEither es a) Source #

withExcepts :: forall m (es :: [Type]) a b. Monad m => (VEither es a -> m b) -> Excepts es m a -> Excepts es m b Source #

withExcepts_ :: forall m (es :: [Type]) a. Monad m => (VEither es a -> m ()) -> Excepts es m a -> Excepts es m a Source #

mapExcepts :: forall m (es :: [Type]) a n (es' :: [Type]) b. (m (VEither es a) -> n (VEither es' b)) -> Excepts es m a -> Excepts es' n b Source #

variantToExcepts :: forall (m :: Type -> Type) a (es :: [Type]). Monad m => V (a ': es) -> Excepts es m a Source #

Convert a Variant into a Excepts

veitherToExcepts :: forall (m :: Type -> Type) (es :: [Type]) a. Monad m => VEither es a -> Excepts es m a Source #

Convert a VEither into a Excepts

catchLiftBoth :: forall e (es' :: [Type]) (es'' :: [Type]) (es :: [Type]) a (m :: Type -> Type). (Monad m, e :< es, LiftVariant (Remove e es) es', LiftVariant es'' es') => (e -> Excepts es'' m a) -> Excepts es m a -> Excepts es' m a Source #

Handle an exception. Lift both normal and exceptional flows into the result flow

catchLiftLeft :: forall e (es :: [Type]) (es' :: [Type]) a (m :: Type -> Type). (Monad m, e :< es, LiftVariant (Remove e es) es') => (e -> Excepts es' m a) -> Excepts es m a -> Excepts es' m a Source #

Handle an exception. Lift the remaining errors into the resulting flow

catchLiftRight :: forall e (es :: [Type]) (es' :: [Type]) a (m :: Type -> Type). (Monad m, e :< es, LiftVariant es' (Remove e es)) => (e -> Excepts es' m a) -> Excepts es m a -> Excepts (Remove e es) m a Source #

Handle an exception. Lift the handler into the resulting flow

catchAllE :: forall (m :: Type -> Type) (es :: [Type]) (es' :: [Type]) a. Monad m => (V es -> Excepts es' m a) -> Excepts es m a -> Excepts es' m a Source #

Do something in case of error

catchDieE :: forall e (es :: [Type]) m a. (e :< es, Monad m) => (e -> m ()) -> Excepts es m a -> Excepts (Remove e es) m a Source #

Catch and die in case of error

catchRemove :: forall e (es :: [Type]) a (m :: Type -> Type). Monad m => (e -> Excepts es m a) -> Excepts (e ': es) m a -> Excepts es m a Source #

Handle an exception. Assume it is in the first position

sequenceE :: forall b (e2 :: [Type]) (m :: Type -> Type) (e1 :: [Type]) a. (KnownNat (Length (b ': e2)), Monad m) => Excepts e1 m a -> Excepts e2 m b -> Excepts (Tail (Product (a ': e1) (b ': e2))) m (a, b) Source #

Product of the sequential execution of two Excepts

The second one is run even if the first one failed!

runBothE :: forall b (e2 :: [Type]) m (e1 :: [Type]) a. (KnownNat (Length (b ': e2)), Monad m) => (forall x y. m x -> m y -> m (x, y)) -> Excepts e1 m a -> Excepts e2 m b -> Excepts (Tail (Product (a ': e1) (b ': e2))) m (a, b) Source #

Product of the execution of two Excepts

You can use a generic monad combinator such as concurrently (in "async" package) to get concurrent execution.

> concurrentE = runBothE concurrently

Reexport