Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data Envelope es a
- = ErrEnvelope (OpenUnion es)
- | SuccEnvelope a
- toSuccEnvelope :: a -> Envelope es a
- toErrEnvelope :: IsMember e es => e -> Envelope es a
- pureSuccEnvelope :: Applicative m => a -> m (Envelope es a)
- pureErrEnvelope :: (Applicative m, IsMember e es) => e -> m (Envelope es a)
- envelope :: (OpenUnion es -> c) -> (a -> c) -> Envelope es a -> c
- emptyEnvelope :: Envelope '[] a -> a
- fromEnvelope :: (OpenUnion es -> a) -> Envelope es a -> a
- fromEnvelopeOr :: Envelope es a -> (OpenUnion es -> a) -> a
- fromEnvelopeM :: Applicative m => (OpenUnion es -> m a) -> Envelope es a -> m a
- fromEnvelopeOrM :: Applicative m => Envelope es a -> (OpenUnion es -> m a) -> m a
- errEnvelopeMatch :: forall e es a. IsMember e es => Envelope es a -> Maybe e
- catchesEnvelope :: forall tuple es a x. ToOpenProduct tuple (ReturnX x es) => tuple -> (a -> x) -> Envelope es a -> x
- envelopeRemove :: forall e es a. ElemRemove e es => Envelope es a -> Either (Envelope (Remove e es) a) e
- envelopeHandle :: ElemRemove e es => (Envelope (Remove e es) a -> x) -> (e -> x) -> Envelope es a -> x
- relaxEnvelope :: Contains es biggerEs => Envelope es a -> Envelope biggerEs a
- liftA2Envelope :: (Contains es1 fullEs, Contains es2 fullEs) => (a -> b -> c) -> Envelope es1 a -> Envelope es2 b -> Envelope fullEs c
- bindEnvelope :: (Contains es1 fullEs, Contains es2 fullEs) => Envelope es1 a -> (a -> Envelope es2 b) -> Envelope fullEs b
- _SuccEnvelope :: Prism (Envelope es a) (Envelope es b) a b
- _ErrEnvelope :: Prism (Envelope es a) (Envelope es' a) (OpenUnion es) (OpenUnion es')
- _ErrEnvelopeErr :: forall e es a. IsMember e es => Prism' (Envelope es a) e
- envelopeToEither :: Envelope es a -> Either (OpenUnion es) a
- eitherToEnvelope :: Either (OpenUnion es) a -> Envelope es a
- isoEnvelopeEither :: Iso (Envelope es a) (Envelope fs b) (Either (OpenUnion es) a) (Either (OpenUnion fs) b)
- data EnvelopeT es m a = EnvelopeT {
- runEnvelopeT :: m (Envelope es a)
- pureSuccEnvT :: Applicative m => a -> EnvelopeT es m a
- throwErrEnvT :: (Applicative m, IsMember e es) => e -> EnvelopeT es m a
- envelopeT :: Monad m => (OpenUnion es -> m c) -> (a -> m c) -> EnvelopeT es m a -> m c
- fromEnvT :: Monad m => (OpenUnion es -> m a) -> EnvelopeT es m a -> m a
- fromEnvTOr :: Monad m => EnvelopeT es m a -> (OpenUnion es -> m a) -> m a
- errEnvTMatch :: forall e es m a. (Functor m, IsMember e es) => EnvelopeT es m a -> m (Maybe e)
- 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
- emptyEnvT :: Functor m => EnvelopeT '[] m a -> m a
- envTRemove :: forall e es m a. (ElemRemove e es, Functor m) => EnvelopeT es m a -> EnvelopeT (Remove e es) m (Either a e)
- relaxEnvT :: (Functor m, Contains es1 es2) => EnvelopeT es1 m a -> EnvelopeT es2 m a
- liftA2EnvT :: (Contains es1 fullEs, Contains es2 fullEs, Applicative m) => (a -> b -> c) -> EnvelopeT es1 m a -> EnvelopeT es2 m b -> EnvelopeT fullEs m c
- bindEnvT :: (Contains es1 fullEs, Contains es2 fullEs, Monad m) => EnvelopeT es1 m a -> (a -> EnvelopeT es2 m b) -> EnvelopeT fullEs m b
- envTToExceptT :: Functor m => EnvelopeT es m a -> ExceptT (OpenUnion es) m a
- exceptTToEnvT :: Functor m => ExceptT (OpenUnion es) m a -> EnvelopeT es m a
Envelope
This Envelope
type is a used as a wrapper around either an OpenUnion
with an error or a successful value. It is similar to an
,
but where the Either
e ae
is specialized to
. The most important
difference from OpenUnion
esEither
is the the FromJSON
and ToJSON
instances.
Given an
, we know that the envelope
could be a Envelope
'[String
, Double
] ()SuccEnvelope
and contain ()
. Or it could be a ErrEnvelope
that contains either a String
or a Double
. It might be simpler to
think of it as a type like
.Either
String
(Either
Double
())
An Envelope
can be created with the toErrEnvelope
and toSuccEnvelope
functions. The Prism
s _SuccEnvelope
, _ErrEnvelope
, and
_ErrEnvelopeErr
can be used to get values out of an Envelope
.
ErrEnvelope (OpenUnion es) | |
SuccEnvelope a |
Instances
Monad (Envelope es) Source # | |
Functor (Envelope es) Source # | |
MonadFix (Envelope es) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope | |
Applicative (Envelope es) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope | |
Foldable (Envelope es) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope fold :: Monoid m => Envelope es m -> m # foldMap :: Monoid m => (a -> m) -> Envelope es a -> m # foldr :: (a -> b -> b) -> b -> Envelope es a -> b # foldr' :: (a -> b -> b) -> b -> Envelope es a -> b # foldl :: (b -> a -> b) -> b -> Envelope es a -> b # foldl' :: (b -> a -> b) -> b -> Envelope es a -> b # foldr1 :: (a -> a -> a) -> Envelope es a -> a # foldl1 :: (a -> a -> a) -> Envelope es a -> a # toList :: Envelope es a -> [a] # null :: Envelope es a -> Bool # length :: Envelope es a -> Int # elem :: Eq a => a -> Envelope es a -> Bool # maximum :: Ord a => Envelope es a -> a # minimum :: Ord a => Envelope es a -> a # | |
Traversable (Envelope es) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope | |
Show (OpenUnion es) => Show1 (Envelope es) Source # | |
(Eq (OpenUnion es), Eq a) => Eq (Envelope es a) Source # | |
(Data (OpenUnion es), Data a, Typeable es) => Data (Envelope es a) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Envelope es a -> c (Envelope es a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Envelope es a) # toConstr :: Envelope es a -> Constr # dataTypeOf :: Envelope es a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Envelope es a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Envelope es a)) # gmapT :: (forall b. Data b => b -> b) -> Envelope es a -> Envelope es a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Envelope es a -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Envelope es a -> r # gmapQ :: (forall d. Data d => d -> u) -> Envelope es a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Envelope es a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Envelope es a -> m (Envelope es a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Envelope es a -> m (Envelope es a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Envelope es a -> m (Envelope es a) # | |
(Ord (OpenUnion es), Ord a) => Ord (Envelope es a) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope compare :: Envelope es a -> Envelope es a -> Ordering # (<) :: Envelope es a -> Envelope es a -> Bool # (<=) :: Envelope es a -> Envelope es a -> Bool # (>) :: Envelope es a -> Envelope es a -> Bool # (>=) :: Envelope es a -> Envelope es a -> Bool # | |
(Read (OpenUnion es), Read a) => Read (Envelope es a) Source # | |
(Show (OpenUnion es), Show a) => Show (Envelope es a) Source # | |
Generic (Envelope es a) Source # | |
Semigroup (Envelope es a) Source # | |
(ToJSON (OpenUnion es), ToJSON a) => ToJSON (Envelope es a) Source # | This Here is an example of a
Here is an example of a
|
Defined in Servant.Checked.Exceptions.Internal.Envelope | |
(FromJSON (OpenUnion es), FromJSON a) => FromJSON (Envelope es a) Source # | This is only a valid instance when the For an explanation, see the documentation on the |
ToSample a => ToSample (Envelope es a) Source # | We can generate a sample of an This doesn't need to worry about generating a sample of |
type Rep (Envelope es a) Source # | |
Defined in Servant.Checked.Exceptions.Internal.Envelope type Rep (Envelope es a) = D1 (MetaData "Envelope" "Servant.Checked.Exceptions.Internal.Envelope" "servant-checked-exceptions-core-2.2.0.0-JjWNBThNKuA7FPLuqPs8C0" False) (C1 (MetaCons "ErrEnvelope" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (OpenUnion es))) :+: C1 (MetaCons "SuccEnvelope" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a))) |
Helper functions
Envelope constructors
toSuccEnvelope :: a -> Envelope es a Source #
This is a function to create a SuccEnvelope
.
>>>
toSuccEnvelope "hello" :: Envelope '[Double] String
SuccEnvelope "hello"
toErrEnvelope :: IsMember e es => e -> Envelope es a Source #
Create an ErrEnvelope
from a member of the OpenUnion
.
For instance, here is how to create an ErrEnvelope
that contains a
Double
:
>>>
let double = 3.5 :: Double
>>>
toErrEnvelope double :: Envelope '[String, Double, Int] ()
ErrEnvelope (Identity 3.5)
pureSuccEnvelope :: Applicative m => a -> m (Envelope es a) Source #
pureSuccEnvelope
is toSuccEnvelope
lifted up to an Applicative
.
>>>
pureSuccEnvelope 3 :: Maybe (Envelope '[Char] Int)
Just (SuccEnvelope 3)
pureErrEnvelope :: (Applicative m, IsMember e es) => e -> m (Envelope es a) Source #
pureErrEnvelope
is toErrEnvelope
lifted up to an Applicative
.
>>>
pureErrEnvelope 'c' :: Maybe (Envelope '[Char] Int)
Just (ErrEnvelope (Identity 'c'))
Envelope destructors
envelope :: (OpenUnion es -> c) -> (a -> c) -> Envelope es a -> c Source #
Case analysis for Envelope
s.
Examples
Here is an example of matching on a SuccEnvelope
:
>>>
let env = toSuccEnvelope "hello" :: Envelope '[Double, Int] String
>>>
envelope (const "not a String") id env
"hello"
Here is an example of matching on a ErrEnvelope
:
>>>
let double = 3.5 :: Double
>>>
let env' = toErrEnvelope double :: Envelope '[Double, Int] String
>>>
envelope (const "not a String") id env'
"not a String"
emptyEnvelope :: Envelope '[] a -> a Source #
Unwrap an Envelope
that cannot contain an error.
Examples
>>>
let env = toSuccEnvelope "hello" :: Envelope '[] String
>>>
emptyEnvelope env
"hello"
fromEnvelope :: (OpenUnion es -> a) -> Envelope es a -> a Source #
Just like fromEither
but for Envelope
.
Examples
Here is an example of successfully matching:
>>>
let env = toSuccEnvelope "hello" :: Envelope '[Double, Int] String
>>>
fromEnvelope (const "not a String") env
"hello"
Here is an example of unsuccessfully matching:
>>>
let double = 3.5 :: Double
>>>
let env' = toErrEnvelope double :: Envelope '[Double, Int] String
>>>
fromEnvelope (const "not a String") env'
"not a String"
fromEnvelopeOr :: Envelope es a -> (OpenUnion es -> a) -> a Source #
Flipped version of fromEnvelope
.
fromEnvelopeM :: Applicative m => (OpenUnion es -> m a) -> Envelope es a -> m a Source #
Lifted version of fromEnvelope
.
fromEnvelopeOrM :: Applicative m => Envelope es a -> (OpenUnion es -> m a) -> m a Source #
Flipped version of fromEnvelopeM
.
errEnvelopeMatch :: forall e es a. IsMember e es => Envelope es a -> Maybe e Source #
Pull out a specific e
from an ErrEnvelope
.
Examples
Successfully pull out an e
:
>>>
let double = 3.5 :: Double
>>>
let env = toErrEnvelope double :: Envelope '[Double] ()
>>>
errEnvelopeMatch env :: Maybe Double
Just 3.5
Unsuccessfully pull out an e
:
>>>
let env' = toSuccEnvelope () :: Envelope '[Double] ()
>>>
errEnvelopeMatch env' :: Maybe Double
Nothing>>>
let env'' = toErrEnvelope 'c' :: Envelope '[Double, Char] ()
>>>
errEnvelopeMatch env'' :: Maybe Double
Nothing
catchesEnvelope :: forall tuple es a x. ToOpenProduct tuple (ReturnX x es) => tuple -> (a -> x) -> Envelope es a -> x Source #
An alternate case anaylsis for an Envelope
. This method uses a tuple
containing handlers for each potential value of the 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 catchesEnvelope
than envelope
.
Examples
Here is an example of handling an SuccEnvelope
with two possible error values.
Notice that a normal tuple is used:
>>>
let env = toSuccEnvelope 2.0 :: Envelope '[Int, String] Double
>>>
let intHandler = (\int -> show int) :: Int -> String
>>>
let strHandler = (\str -> str) :: String -> String
>>>
let succHandler = (\dbl -> "got a double") :: Double -> String
>>>
catchesEnvelope (intHandler, strHandler) succHandler env :: 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 = toErrEnvelope (3 :: Int) :: Envelope '[Int, String] Double
>>>
let intHandler = (\int -> show int) :: Int -> String
>>>
let strHandler = (\str -> str) :: String -> String
>>>
let succHandler = (\dbl -> "got a double") :: Double -> String
>>>
catchesEnvelope (intHandler, strHandler) succHandler env :: String
"3"
Given an Envelope
like
, the type of
Envelope
'[Int
, String
] Double
catchesEnvelope
becomes the following:
catchesEnvelope
:: (Int
-> x,String
-> x) -> (Double
-> x) ->Envelope
'[Int
,String
]Double
-> 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 = toErrEnvelope ("hi" :: String) :: Envelope '[Int, String, Char] Double
>>>
let intHandler = (\int -> show int) :: Int -> String
>>>
let strHandler = (\str -> str) :: String -> String
>>>
let chrHandler = (\chr -> [chr]) :: Char -> String
>>>
let succHandler = (\dbl -> "got a double") :: Double -> String
>>>
catchesEnvelope (intHandler, strHandler, chrHandler) succHandler env :: String
"hi"
Given an Envelope
like
,
the type of Envelope
'[Int
, String
, Char
] Double
catchesEnvelope
becomes the following:
catchesEnvelope
:: (Int
-> x,String
-> x,Char
-> x) -> (Double
-> x) ->Envelope
'[Int
,String
,Char
]Double
-> x
Here is an example of handling an ErrEnvelope
with only one possible error value.
Notice that a normal handler is used (not a tuple):
>>>
let env = toErrEnvelope (3 :: Int) :: Envelope '[Int] Double
>>>
let intHandler = (\int -> show int) :: Int -> String
>>>
let succHandler = (\dbl -> "got a double") :: Double -> String
>>>
catchesEnvelope intHandler succHandler env :: String
"3"
Given an Envelope
like
, the type of
Envelope
'[Int
] Double
catchesEnvelope
becomes the following:
catchesEnvelope
:: (Int
-> x) -> (Double
-> x) ->Envelope
'[Int
]Double
-> x
envelopeRemove :: forall e es a. ElemRemove e es => Envelope es a -> Either (Envelope (Remove e es) a) e Source #
This function allows you to try to remove individual error types from an
Envelope
.
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 catchesEnvelope
.
Examples
Pulling out an error in an Envelope
:
>>>
let env1 = toErrEnvelope "hello" :: Envelope '[String, Double] Float
>>>
envelopeRemove env1 :: Either (Envelope '[Double] Float) String
Right "hello"
Failing to pull out an error in an Envelope
:
>>>
let env2 = toErrEnvelope (3.5 :: Double) :: Envelope '[String, Double] Float
>>>
envelopeRemove env2 :: Either (Envelope '[Double] Float) String
Left (ErrEnvelope (Identity 3.5))
Note that if you have an Envelope
with multiple errors of the same type,
they will all be handled at the same time:
>>>
let env3 = toErrEnvelope (3.5 :: Double) :: Envelope '[String, Double, Char, Double] Float
>>>
envelopeRemove env3 :: Either (Envelope '[String, Char] Float) Double
Right 3.5
SuccEnvelope
gets passed through as expected:
>>>
let env4 = toSuccEnvelope 3.5 :: Envelope '[String, Double] Float
>>>
envelopeRemove env4 :: Either (Envelope '[Double] Float) String
Left (SuccEnvelope 3.5)
envelopeHandle :: ElemRemove e es => (Envelope (Remove e es) a -> x) -> (e -> x) -> Envelope es a -> x Source #
Handle a single case in an Envelope
. This is similar to envelope
but lets you handle any case within the Envelope
, not just the first one.
Examples
Handling the first item in an Envelope
:
>>>
let env1 = toErrEnvelope 3.5 :: Envelope '[Double, Int] Char
>>>
let printDouble = print :: Double -> IO ()
>>>
let printEnv = print :: Envelope '[Int] Char -> IO ()
>>>
envelopeHandle printEnv printDouble env1
3.5
Handling a middle item in an Envelope
:
>>>
let env2 = toErrEnvelope (3.5 :: Double) :: Envelope '[Char, Double, Int] Float
>>>
let printEnv = print :: Envelope '[Char, Int] Float -> IO ()
>>>
envelopeHandle printEnv printDouble env2
3.5
Failing to handle an item in an Envelope
. In the following example, the
printEnv
function is called:
>>>
let env3 = toErrEnvelope 'c' :: Envelope '[Char, Double, Int] Float
>>>
let printEnv = print :: Envelope '[Char, Int] Float -> IO ()
>>>
envelopeHandle printEnv printDouble env3
ErrEnvelope (Identity 'c')
If you have duplicates in your Envelope
, they will both get handled with
a single call to unionHandle
.
>>>
let env4 = toErrEnvelope 3.5 :: Envelope '[Double, Double, Int] Char
>>>
let printEnv = print :: Envelope '[Int] Char -> IO ()
>>>
envelopeHandle printEnv printDouble env4
3.5
SuccEnvelope
gets passed through as expected:
>>>
let env5 = toSuccEnvelope 3.5 :: Envelope '[String, Double] Float
>>>
let printEnv = print :: Envelope '[String] Float -> IO ()
>>>
envelopeHandle printEnv printDouble env5
SuccEnvelope 3.5
Other Envelope combinators
relaxEnvelope :: Contains es biggerEs => Envelope es a -> Envelope biggerEs a Source #
Change the errors type in an Envelope
to a larger set.
>>>
let double = 3.5 :: Double
>>>
let env = toErrEnvelope double :: Envelope '[Double, Int] Char
>>>
relaxEnvelope env :: Envelope '[(), Int, Double, String] Char
ErrEnvelope (Identity 3.5)
liftA2Envelope :: (Contains es1 fullEs, Contains es2 fullEs) => (a -> b -> c) -> Envelope es1 a -> Envelope es2 b -> Envelope fullEs c Source #
Similar to liftA2
, but more general. This allows you to operate on two
Envelope
s with different sets of errors. The resulting Envelope
is a
combination of the errors in each of the input Envelope
s.
Examples
>>>
let env1 = toSuccEnvelope "hello" :: Envelope '[Double, Int] String
>>>
let env2 = toSuccEnvelope " world" :: Envelope '[Char] String
>>>
liftA2Envelope (<>) env1 env2 :: Envelope '[Double, Int, Char] String
SuccEnvelope "hello world"
If either of the Envelope
s is an ErrEnvelope
, then return the ErrEnvelope
.
>>>
let env3 = toErrEnvelope "some err" :: Envelope '[String, Double] Int
>>>
let env4 = toSuccEnvelope 1 :: Envelope '[Char] Int
>>>
liftA2Envelope (+) env3 env4 :: Envelope '[String, Double, Char] Int
ErrEnvelope (Identity "some err")
>>>
let env5 = toSuccEnvelope "hello" :: Envelope '[Char] String
>>>
let env6 = toErrEnvelope 3.5 :: Envelope '[(), Double] String
>>>
liftA2Envelope (<>) env5 env6 :: Envelope '[Char, (), Double] String
ErrEnvelope (Identity 3.5)
If both of the Envelope
s is an ErrEnvelope
, then short-circuit and only
return the first ErrEnvelope
.
>>>
let env7 = toErrEnvelope 3.5 :: Envelope '[(), Double] String
>>>
let env8 = toErrEnvelope 'x' :: Envelope '[Int, Char] String
>>>
liftA2Envelope (<>) env7 env8 :: Envelope '[(), Double, Int, Char] String
ErrEnvelope (Identity 3.5)
bindEnvelope :: (Contains es1 fullEs, Contains es2 fullEs) => Envelope es1 a -> (a -> Envelope es2 b) -> Envelope fullEs b Source #
This is like liftA2Envelope
but for monadic bind (>>=
).
This allows you to bind on Envelope
s that contain different errors.
The resulting Envelope
must have a superset of the errors in two input
Envelope
s.
Examples
>>>
let env1 = toSuccEnvelope "hello" :: Envelope '[Double, Int] String
>>>
let f1 str = toSuccEnvelope (length str) :: Envelope '[Char] Int
>>>
bindEnvelope env1 f1 :: Envelope '[Double, Int, Char] Int
SuccEnvelope 5
If either of the Envelope
s is an ErrEnvelope
, then return the ErrEnvelope
.
>>>
let env2 = toErrEnvelope "some err" :: Envelope '[String, Double] Int
>>>
let f2 i = toSuccEnvelope (i + 1) :: Envelope '[Char] Int
>>>
bindEnvelope env2 f2 :: Envelope '[String, Double, Char] Int
ErrEnvelope (Identity "some err")
>>>
let env3 = toSuccEnvelope "hello" :: Envelope '[Char] String
>>>
let f3 _ = toErrEnvelope 3.5 :: Envelope '[(), Double] Int
>>>
bindEnvelope env3 f3 :: Envelope '[Char, (), Double] Int
ErrEnvelope (Identity 3.5)
If both of the Envelope
s is an ErrEnvelope
, then short-circuit and only
return the first ErrEnvelope
.
>>>
let env4 = toErrEnvelope 3.5 :: Envelope '[(), Double] String
>>>
let f4 _ = toErrEnvelope 'x' :: Envelope '[Int, Char] String
>>>
bindEnvelope env4 f4 :: Envelope '[Char, (), Double, Int] String
ErrEnvelope (Identity 3.5)
Optics
_SuccEnvelope :: Prism (Envelope es a) (Envelope es b) a b Source #
Lens-compatible Prism
to pull out an a
from a SuccEnvelope
.
Examples
Use _SuccEnvelope
to construct an Envelope
:
>>>
review _SuccEnvelope "hello" :: Envelope '[Double] String
SuccEnvelope "hello"
Use _SuccEnvelope
to try to destruct an Envelope
into an a
:
>>>
let env = toSuccEnvelope "hello" :: Envelope '[Double] String
>>>
preview _SuccEnvelope env :: Maybe String
Just "hello"
Use _SuccEnvelope
to try to destruct a 'Envelope into an a
(unsuccessfully):
>>>
let double = 3.5 :: Double
>>>
let env' = toErrEnvelope double :: Envelope '[Double] String
>>>
preview _SuccEnvelope env' :: Maybe String
Nothing
_ErrEnvelope :: Prism (Envelope es a) (Envelope es' a) (OpenUnion es) (OpenUnion es') Source #
Lens-compatible Prism
to pull out an
from a
OpenUnion
esErrEnvelope
.
Most users will not use _ErrEnvelope
, but instead _ErrEnvelopeErr
.
Examples
Use _ErrEnvelope
to construct an Envelope
:
>>>
let string = "hello" :: String
>>>
review _ErrEnvelope (openUnionLift string) :: Envelope '[String] Double
ErrEnvelope (Identity "hello")
Use _ErrEnvelope
to try to destruct an Envelope
into an
:OpenUnion
es
>>>
let double = 3.5 :: Double
>>>
let env = toErrEnvelope double :: Envelope '[Double] ()
>>>
preview _ErrEnvelope env :: Maybe (OpenUnion '[Double])
Just (Identity 3.5)
Use _ErrEnvelope
to try to destruct a 'Envelope into an
(unsuccessfully):OpenUnion
es
>>>
let env' = toSuccEnvelope () :: Envelope '[Double] ()
>>>
preview _ErrEnvelope env' :: Maybe (OpenUnion '[Double])
Nothing
_ErrEnvelopeErr :: forall e es a. IsMember e es => Prism' (Envelope es a) e Source #
Lens-compatible Prism
to pull out a specific e
from an ErrEnvelope
.
Most users will use _ErrEnvelopeErr
instead of _ErrEnvelope
.
Examples
Use _ErrEnvelopeErr
to construct an Envelope
:
>>>
let string = "hello" :: String
>>>
review _ErrEnvelopeErr string :: Envelope '[String] Double
ErrEnvelope (Identity "hello")
Use _ErrEnvelopeErr
to try to destruct an Envelope
into an e
:
>>>
let double = 3.5 :: Double
>>>
let env = toErrEnvelope double :: Envelope '[Double] ()
>>>
preview _ErrEnvelopeErr env :: Maybe Double
Just 3.5
Use _ErrEnvelopeErr
to try to destruct a 'Envelope into an
e
(unsuccessfully):
>>>
let env' = toSuccEnvelope () :: Envelope '[Double] ()
>>>
preview _ErrEnvelopeErr env' :: Maybe Double
Nothing>>>
let env'' = toErrEnvelope 'c' :: Envelope '[Double, Char] ()
>>>
preview _ErrEnvelopeErr env'' :: Maybe Double
Nothing
Either
isoEnvelopeEither :: Iso (Envelope es a) (Envelope fs b) (Either (OpenUnion es) a) (Either (OpenUnion fs) b) Source #
EnvelopeT
data EnvelopeT es m a Source #
EnvelopeT | |
|
Instances
EnvelopeT constructors
pureSuccEnvT :: Applicative m => a -> EnvelopeT es m a Source #
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 destructors
envelopeT :: Monad m => (OpenUnion es -> m c) -> (a -> m c) -> EnvelopeT es m a -> m c Source #
Case analysis for EnvelopeT
.
Examples
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
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
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
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
,
the type of EnvelopeT
'[Int
, String
] IO
Double
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
,
the type of EnvelopeT
'[Int
, String
, Char
] IO
Double
catchesEnvT
becomes the following:
catchesEnvT
:: (Int
->IO
x,String
->IO
x,Char
->IO
x) -> (Double
->IO
x) ->EnvelopeT
'[Int
,String
,Char
]IO
Double
-> x
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"
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
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)))
Other EnvelopeT combinators
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
>>>
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 EnvelopeT
s. Generalize the set of errors to include the errors
from both EnvelopeT
s. Similar to liftA2
but more general.
Examples
>>>
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 Envelope
s 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 EnvelopeT
s 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 EnvelopeT
s that contain different errors.
The resulting EnvelopeT
must have a superset of the errors in two input
EnvelopeT
s.
Examples
>>>
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 EnvelopeT
s 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 Envelope
s 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)))