servant-checked-exceptions-core-2.2.0.1: Checked exceptions for Servant APIs.
CopyrightDennis Gosnell 2019
LicenseBSD3
MaintainerDennis Gosnell (cdep.illabout@gmail.com)
Stabilityexperimental
Portabilityunknown
Safe HaskellNone
LanguageHaskell2010

Servant.Checked.Exceptions.Internal.EnvelopeT

Description

This module defines the EnvelopeT type and helper functions. EnvelopeT is a short-circuiting monad transformer.

Envelope is similar to Either where multiple errors types are possible. EnvelopeT is similar to ExceptT in a similar manner.

Synopsis

Documentation

>>> :set -XDataKinds
>>> :set -XTypeOperators
>>> import Data.Functor.Identity (Identity(Identity))

data EnvelopeT es m a Source #

Constructors

EnvelopeT 

Fields

Instances

Instances details
MonadRWS r w s m => MonadRWS r w s (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

MonadReader r m => MonadReader r (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

ask :: EnvelopeT es m r #

local :: (r -> r) -> EnvelopeT es m a -> EnvelopeT es m a #

reader :: (r -> a) -> EnvelopeT es m a #

MonadState s m => MonadState s (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

get :: EnvelopeT es m s #

put :: s -> EnvelopeT es m () #

state :: (s -> (a, s)) -> EnvelopeT es m a #

MonadError error m => MonadError error (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

throwError :: error -> EnvelopeT es m a #

catchError :: EnvelopeT es m a -> (error -> EnvelopeT es m a) -> EnvelopeT es m a #

MonadWriter w m => MonadWriter w (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

writer :: (a, w) -> EnvelopeT es m a #

tell :: w -> EnvelopeT es m () #

listen :: EnvelopeT es m a -> EnvelopeT es m (a, w) #

pass :: EnvelopeT es m (a, w -> w) -> EnvelopeT es m a #

MonadTrans (EnvelopeT es) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

lift :: Monad m => m a -> EnvelopeT es m a #

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

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

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

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

return :: a -> EnvelopeT es m a #

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

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

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

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

Monad m => Applicative (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

pure :: a -> EnvelopeT es m a #

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

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

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

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

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

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

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

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

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

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

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

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

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

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

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

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

null :: EnvelopeT es m a -> Bool #

length :: EnvelopeT es m a -> Int #

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

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

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

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

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

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

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

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

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

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

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

Contravariant m => Contravariant (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

contramap :: (a -> b) -> EnvelopeT es m b -> EnvelopeT es m a #

(>$) :: b -> EnvelopeT es m b -> EnvelopeT es m a #

(Show (OpenUnion es), Show1 m) => Show1 (EnvelopeT es m) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> EnvelopeT es m a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [EnvelopeT es m a] -> ShowS #

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

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

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

(Show (OpenUnion e), Show1 m, Show a) => Show (EnvelopeT e m a) Source # 
Instance details

Defined in Servant.Checked.Exceptions.Internal.EnvelopeT

Methods

showsPrec :: Int -> EnvelopeT e m a -> ShowS #

show :: EnvelopeT e m a -> String #

showList :: [EnvelopeT e m a] -> ShowS #

pureSuccEnvT :: Applicative m => a -> EnvelopeT es m a Source #

This is pure for EnvelopeT.

>>> pureSuccEnvT "hello" :: EnvelopeT '[] Identity String
EnvelopeT (Identity (SuccEnvelope "hello"))

throwErrEnvT :: (Applicative m, IsMember e es) => e -> EnvelopeT es m a Source #

Throw an error in an ErrEnvelope.

>>> let double = 3.5 :: Double
>>> throwErrEnvT double :: EnvelopeT '[String, Double, Int] Identity ()
EnvelopeT (Identity (ErrEnvelope (Identity 3.5)))

This is similar to throwError, but is specialized so you can throw just one of the error types.

envelopeT :: Monad m => (OpenUnion es -> m c) -> (a -> m c) -> EnvelopeT es m a -> m c Source #

Case analysis for EnvelopeT.

Examples

Expand

Here is an example of matching on a SuccEnvelope:

>>> let env = pure "hello" :: EnvelopeT '[Double, Int] Identity String
>>> envelopeT (\_ -> Identity "not a String") Identity env
Identity "hello"

Here is an example of matching on a ErrEnvelope:

>>> let double = 3.5 :: Double
>>> let env' = throwErrEnvT double :: EnvelopeT '[Double, Int] Identity String
>>> envelopeT (\_ -> Identity "not a String") Identity env'
Identity "not a String"

fromEnvT :: Monad m => (OpenUnion es -> m a) -> EnvelopeT es m a -> m a Source #

Slight simplification of envelopeT.

Examples

Expand

Here is an example of successfully matching:

>>> let env = pure "hello" :: EnvelopeT '[Double, Int] Identity String
>>> fromEnvT (\_ -> Identity "not a String") env
Identity "hello"

Here is an example of unsuccessfully matching:

>>> let double = 3.5 :: Double
>>> let env' = throwErrEnvT double :: EnvelopeT '[Double, Int] Identity String
>>> fromEnvT (\_ -> Identity "not a String") env'
Identity "not a String"

fromEnvTOr :: Monad m => EnvelopeT es m a -> (OpenUnion es -> m a) -> m a Source #

Flipped version of fromEnvT.

errEnvTMatch :: forall e es m a. (Functor m, IsMember e es) => EnvelopeT es m a -> m (Maybe e) Source #

Try to pull out a specific e from an ErrEnvelope.

Examples

Expand

Successfully pull out an e:

>>> let double = 3.5 :: Double
>>> let env = throwErrEnvT double :: EnvelopeT '[Double, Char] Identity ()
>>> errEnvTMatch env :: Identity (Maybe Double)
Identity (Just 3.5)

Unsuccessfully pull out an e:

>>> let env' = pure () :: EnvelopeT '[String, Double] Identity ()
>>> errEnvTMatch env' :: Identity (Maybe Double)
Identity Nothing

catchesEnvT :: forall tuple es m a x. (Monad m, ToOpenProduct tuple (ReturnX (m x) es)) => tuple -> (a -> m x) -> EnvelopeT es m a -> m x Source #

An alternate case anaylsis for an EnvelopeT. This method uses a tuple containing handlers for each potential value of the underlying Envelope. This is somewhat similar to the catches function.

When working with an Envelope with a large number of possible error types, it can be easier to use catchesEnvT than envelopeT.

Examples

Expand

Here is an example of handling an SuccEnvelope with two possible error values. Notice that a normal tuple is used:

>>> let env = pure 2.0 :: EnvelopeT '[Int, String] IO Double
>>> let intHandler = (\int -> pure $ show int) :: Int -> IO String
>>> let strHandler = (\str -> pure str) :: String -> IO String
>>> let succHandler = (\dbl -> pure "got a double") :: Double -> IO String
>>> catchesEnvT (intHandler, strHandler) succHandler env :: IO String
"got a double"

Here is an example of handling an ErrEnvelope with two possible error values. Notice that a normal tuple is used to hold the handlers:

>>> let env = throwErrEnvT (3 :: Int) :: EnvelopeT '[Int, String] Identity Double
>>> let intHandler = (\int -> Identity $ show int) :: Int -> Identity String
>>> let strHandler = (\str -> Identity str) :: String -> Identity String
>>> let succHandler = (\dbl -> Identity "got a double") :: Double -> Identity String
>>> catchesEnvT (intHandler, strHandler) succHandler env :: Identity String
Identity "3"

Given an EnvelopeT like EnvelopeT '[Int, String] IO Double, the type of catchesEnvT becomes the following:

  catchesEnvT
    :: (Int -> IO x, String -> IO x)
    -> (Double -> IO x)
    -> EnvelopeT '[Int, String] IO Double
    -> IO x

Here is an example of handling an ErrEnvelope with three possible values. Notice how a 3-tuple is used to hold the handlers:

>>> let env = throwErrEnvT ("hi" :: String) :: EnvelopeT '[Int, String, Char] IO Double
>>> let intHandler = (\int -> pure $ show int) :: Int -> IO String
>>> let strHandler = (\str -> pure str) :: String -> IO String
>>> let chrHandler = (\chr -> pure [chr]) :: Char -> IO String
>>> let succHandler = (\dbl -> pure "got a double") :: Double -> IO String
>>> catchesEnvT (intHandler, strHandler, chrHandler) succHandler env :: IO String
"hi"

Given an Envelope like EnvelopeT '[Int, String, Char] IO Double, the type of catchesEnvT becomes the following:

  catchesEnvT
    :: (Int -> IO x, String -> IO x, Char -> IO x)
    -> (Double -> IO x)
    -> EnvelopeT '[Int, String, Char] IO Double
    -> x

envTToExceptT :: Functor m => EnvelopeT es m a -> ExceptT (OpenUnion es) m a Source #

Convert an EnvelopeT to an ExceptT.

exceptTToEnvT :: Functor m => ExceptT (OpenUnion es) m a -> EnvelopeT es m a Source #

Convert an ExceptT to an EnvelopeT.

emptyEnvT :: Functor m => EnvelopeT '[] m a -> m a Source #

Safely unwrap an EnvelopeT.

>>> let myenvT = pure "hello" :: EnvelopeT '[] IO String
>>> emptyEnvT myenvT :: IO String
"hello"

relaxEnvT :: (Functor m, Contains es1 es2) => EnvelopeT es1 m a -> EnvelopeT es2 m a Source #

Change the errors type in an EnvelopeT to a larger set.

Examples

Expand
>>> let double = 3.5 :: Double
>>> let envT1 = throwErrEnvT double :: EnvelopeT '[Int, Double] Identity Float
>>> relaxEnvT envT1 :: EnvelopeT '[Char, Int, String, Double] Identity Float
EnvelopeT (Identity (ErrEnvelope (Identity 3.5)))
>>> let envT2 = pure double :: EnvelopeT '[Char, Int] Identity Double
>>> relaxEnvT envT2 :: EnvelopeT '[(), Char, String, Int] Identity Double
EnvelopeT (Identity (SuccEnvelope 3.5))

liftA2EnvT :: (Contains es1 fullEs, Contains es2 fullEs, Applicative m) => (a -> b -> c) -> EnvelopeT es1 m a -> EnvelopeT es2 m b -> EnvelopeT fullEs m c Source #

Combine two EnvelopeTs. Generalize the set of errors to include the errors from both EnvelopeTs. Similar to liftA2 but more general.

Examples

Expand
>>> let env1 = pure "hello" :: EnvelopeT '[Double, Int] Identity String
>>> let env2 = pure " world" :: EnvelopeT '[Char]  Identity String
>>> liftA2EnvT (<>) env1 env2 :: EnvelopeT '[Double, Int, Char] Identity String
EnvelopeT (Identity (SuccEnvelope "hello world"))

If either of the Envelopes is an ErrEnvelope, then return the ErrEnvelope.

>>> let env3 = throwErrEnvT "some err" :: EnvelopeT '[String, Double] Identity Int
>>> let env4 = pure 1 :: EnvelopeT '[Char]  Identity Int
>>> liftA2EnvT (+) env3 env4 :: EnvelopeT '[String, Double, Char] Identity Int
EnvelopeT (Identity (ErrEnvelope (Identity "some err")))
>>> let env5 = pure "hello" :: EnvelopeT '[Char] Identity String
>>> let env6 = throwErrEnvT 3.5 :: EnvelopeT '[(), Double] Identity String
>>> liftA2EnvT (<>) env5 env6 :: EnvelopeT '[Char, (), Double] Identity String
EnvelopeT (Identity (ErrEnvelope (Identity 3.5)))

If both of the EnvelopeTs is an ErrEnvelope, then short-circuit and only return the first ErrEnvelope.

>>> let env7 = throwErrEnvT 4.5 :: EnvelopeT '[(), Double] Identity String
>>> let env8 = throwErrEnvT 'x' :: EnvelopeT '[Int, Char] Identity String
>>> liftA2EnvT (<>) env7 env8 :: EnvelopeT '[(), Double, Int, Char] Identity String
EnvelopeT (Identity (ErrEnvelope (Identity 4.5)))

bindEnvT :: (Contains es1 fullEs, Contains es2 fullEs, Monad m) => EnvelopeT es1 m a -> (a -> EnvelopeT es2 m b) -> EnvelopeT fullEs m b Source #

This is like liftA2EnvT but for monadic bind (>>=).

This allows you to bind on EnvelopeTs that contain different errors.

The resulting EnvelopeT must have a superset of the errors in two input EnvelopeTs.

Examples

Expand
>>> let env1 = pure "hello" :: EnvelopeT '[Double, Int] Identity String
>>> let f1 str = pure (length str) :: EnvelopeT '[Char] Identity Int
>>> bindEnvT env1 f1 :: EnvelopeT '[Double, Int, Char] Identity Int
EnvelopeT (Identity (SuccEnvelope 5))

If either of the EnvelopeTs holds an ErrEnvelope, then return the ErrEnvelope.

>>> let env2 = throwErrEnvT "some err" :: EnvelopeT '[String, Double] Identity Int
>>> let f2 i = pureSuccEnvT (i + 1) :: EnvelopeT '[Char] Identity Int
>>> bindEnvT env2 f2 :: EnvelopeT '[String, Double, Char] Identity Int
EnvelopeT (Identity (ErrEnvelope (Identity "some err")))
>>> let env3 = pureSuccEnvT "hello" :: EnvelopeT '[Char] Identity String
>>> let f3 _ = throwErrEnvT 3.5 :: EnvelopeT '[(), Double] Identity Int
>>> bindEnvT env3 f3 :: EnvelopeT '[Char, (), Double] Identity Int
EnvelopeT (Identity (ErrEnvelope (Identity 3.5)))

If both of the Envelopes is an ErrEnvelope, then short-circuit and only return the first ErrEnvelope.

>>> let env4 = throwErrEnvT 3.5 :: EnvelopeT '[(), Double] Maybe String
>>> let f4 _ = throwErrEnvT 'x' :: EnvelopeT '[Int, Char] Maybe String
>>> bindEnvT env4 f4 :: EnvelopeT '[Char, (), Double, Int] Maybe String
EnvelopeT (Just (ErrEnvelope (Identity 3.5)))

envTRemove :: forall e es m a. (ElemRemove e es, Functor m) => EnvelopeT es m a -> EnvelopeT (Remove e es) m (Either a e) Source #

This function allows you to try to remove individual error types from an EnvelopeT.

This can be used to handle only certain error types in an Envelope, instead of having to handle all of them at the same time. This can be more convenient than a function like catchesEnvT.

Examples

Expand

Pulling out an error in an EnvelopeT:

>>> let env1 = throwErrEnvT "hello" :: EnvelopeT '[String, Double] Identity Float
>>> envTRemove env1 :: EnvelopeT '[Double] Identity (Either Float String)
EnvelopeT (Identity (SuccEnvelope (Right "hello")))

Failing to pull out an error in an EnvelopeT:

>>> let env2 = throwErrEnvT (3.5 :: Double) :: EnvelopeT '[String, Double] Identity Float
>>> envTRemove env2 :: EnvelopeT '[Double] Identity (Either Float String)
EnvelopeT (Identity (ErrEnvelope (Identity 3.5)))

Note that if you have an EnvelopeT with multiple errors of the same type, they will all be handled at the same time:

>>> let env3 = throwErrEnvT (3.5 :: Double) :: EnvelopeT '[String, Double, Char, Double] Identity Float
>>> envTRemove env3 :: EnvelopeT '[String, Char] Identity (Either Float Double)
EnvelopeT (Identity (SuccEnvelope (Right 3.5)))

SuccEnvelope gets passed through as expected:

>>> let env4 = pureSuccEnvT 3.5 :: EnvelopeT '[String, Double] Identity Float
>>> envTRemove env4 :: EnvelopeT '[Double] Identity (Either Float String)
EnvelopeT (Identity (SuccEnvelope (Left 3.5)))