servant-checked-exceptions 0.3.0.1 → 0.3.0.2
raw patch · 5 files changed
+52/−18 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +4/−4
- servant-checked-exceptions.cabal +1/−1
- src/Servant/Checked/Exceptions/Internal/Envelope.hs +21/−9
- src/Servant/Checked/Exceptions/Internal/Product.hs +3/−1
- src/Servant/Checked/Exceptions/Internal/Union.hs +23/−3
README.md view
@@ -22,19 +22,19 @@ type Api = "author" :> Capture "author-id" AuthorId :>- Throws CouldNotConnectToDbError :>+ Throws DatabaseError :> Throws AuthorNotFoundError :> Get '[JSON] Author -- These are the two errors that can be thrown:-data CouldNotConnectToDbError = CouldNotConnectToDbError+data DatabaseError = DatabaseError data AuthorNotFoundError = AuthorNotFoundError ``` The corresponding handler function uses the [`Envelope`](https://hackage.haskell.org/package/servant-checked-exceptions/docs/Servant-Checked-Exceptions.html#t:Envelope) data type to model the possibility of returning an `Author` successfully, or-either `CouldNotConnectToDbError` or `AuthorNotFoundError` unsuccessfully.+either `DatabaseError` or `AuthorNotFoundError` unsuccessfully. Internally, `Envelope` is using an open sum-type to easily represent multiple different errors: @@ -61,7 +61,7 @@ "update-author-name" :> Capture "author-id" AuthorId :> Capture "author-name" AuthorName :>- Throws CouldNotConnectToDbError :>+ Throws DatabaseError :> Throws AuthorNotFoundError :> Throws AuthorNameTooShort :> Post '[JSON] Author
servant-checked-exceptions.cabal view
@@ -1,5 +1,5 @@ name: servant-checked-exceptions-version: 0.3.0.1+version: 0.3.0.2 synopsis: Checked exceptions for Servant APIs. description: Please see <https://github.com/cdepillabout/servant-checked-exceptions#readme README.md>. homepage: https://github.com/cdepillabout/servant-checked-exceptions
src/Servant/Checked/Exceptions/Internal/Envelope.hs view
@@ -134,6 +134,8 @@ -- | Case analysis for 'Envelope's. --+-- ==== __Examples__+-- -- Here is an example of matching on a 'SuccEnvelope': -- -- >>> let env = toSuccEnvelope "hello" :: Envelope '[Double, Int] String@@ -152,6 +154,8 @@ -- | Just like 'Data.Either.fromEither' but for 'Envelope'. --+-- ==== __Examples__+-- -- Here is an example of successfully matching: -- -- >>> let env = toSuccEnvelope "hello" :: Envelope '[Double, Int] String@@ -199,6 +203,8 @@ -- | Lens-compatible 'Prism' to pull out an @a@ from a 'SuccEnvelope'. --+-- ==== __Examples__+-- -- Use '_SuccEnvelope' to construct an 'Envelope': -- -- >>> review _SuccEnvelope "hello" :: Envelope '[Double] String@@ -223,6 +229,10 @@ -- | Lens-compatible 'Prism' to pull out an @'OpenUnion' es@ from a -- 'ErrEnvelope'. --+-- Most users will not use '_ErrEnvelope', but instead '_ErrEnvelopeErr'.+--+-- ==== __Examples__+-- -- Use '_ErrEnvelope' to construct an 'Envelope': -- -- >>> let string = "hello" :: String@@ -243,13 +253,15 @@ -- >>> let env' = toSuccEnvelope () :: Envelope '[Double] () -- >>> preview _ErrEnvelope env' :: Maybe (OpenUnion '[Double]) -- Nothing------ Most users will not use '_ErrEnvelope', but instead '_ErrEnvelopeErr'. _ErrEnvelope :: Prism (Envelope es a) (Envelope es' a) (OpenUnion es) (OpenUnion es') _ErrEnvelope = prism ErrEnvelope $ envelope Right (Left . SuccEnvelope) -- | 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@@ -272,13 +284,13 @@ -- >>> let env'' = toErrEnvelope 'c' :: Envelope '[Double, Char] () -- >>> preview _ErrEnvelopeErr env'' :: Maybe Double -- Nothing------ Most users will use '_ErrEnvelopeErr' instead of '_ErrEnvelope'. _ErrEnvelopeErr :: forall e es a. IsMember e es => Prism' (Envelope es a) e _ErrEnvelopeErr = _ErrEnvelope . openUnionPrism -- | Pull out a specific @e@ from an 'ErrEnvelope'. --+-- ==== __Examples__+-- -- Successfully pull out an @e@: -- -- >>> let double = 3.5 :: Double@@ -304,6 +316,11 @@ -- containing handlers for each potential value of the 'Envelope'. This is -- somewhat similar to the 'Control.Exception.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: --@@ -376,17 +393,12 @@ -- -> 'Envelope' \'['Int'] 'Double' -- -> x -- @------ When working with an 'Envelope' with a large number of possible error types,--- it can be easier to use 'catchesEnvelope' than 'envelope'. catchesEnvelope :: forall tuple es a x. ToOpenProduct tuple (ReturnX x es) => tuple -> (a -> x) -> Envelope es a -> x catchesEnvelope _ a2x (SuccEnvelope a) = a2x a catchesEnvelope tuple _ (ErrEnvelope u) = catchesOpenUnion tuple u---- data EnvelopeHandler es x = forall e. IsMember e es => EnvelopeHandler (e -> x) -- | This 'ToJSON' instance encodes an 'Envelope' as an object with one of two -- keys depending on whether it is a 'SuccEnvelope' or an 'ErrEnvelope'.
src/Servant/Checked/Exceptions/Internal/Product.hs view
@@ -122,7 +122,9 @@ -- | Turn a tuple into an 'OpenProduct'. ----- For example, turn a triple into an 'OpenProduct':+-- ==== __Examples__+--+-- Turn a triple into an 'OpenProduct': -- -- >>> tupleToOpenProduct (1, 2.0, "hello") :: OpenProduct '[Int, Double, String] -- Cons (Identity 1) (Cons (Identity 2.0) (Cons (Identity "hello") Nil))
src/Servant/Checked/Exceptions/Internal/Union.hs view
@@ -93,6 +93,8 @@ -- | A partial relation that gives the index of a value in a list. --+-- ==== __Examples__+-- -- Find the first item: -- -- >>> import Data.Type.Equality ((:~:)(Refl))@@ -126,6 +128,8 @@ -- | Case analysis for 'Union'. --+-- ==== __Examples__+-- -- Here is an example of matching on a 'This': -- -- >>> let u = This (Identity "hello") :: Union Identity '[String, Int]@@ -149,6 +153,8 @@ -- | Map over the interpretation @f@ in the 'Union'. --+-- ==== __Examples__+-- -- Here is an example of changing a @'Union' 'Identity' \'['String', 'Int']@ to -- @'Union' 'Maybe' \'['String', 'Int']@: --@@ -171,6 +177,8 @@ -- containing handlers for each potential value of the 'Union'. This is -- somewhat similar to the 'Control.Exception.catches' function. --+-- ==== __Examples__+-- -- Here is an example of handling a 'Union' with two possible values. Notice -- that a normal tuple is used: --@@ -198,6 +206,8 @@ -- | Lens-compatible 'Prism' for 'This'. --+-- ==== __Examples__+-- -- Use '_This' to construct a 'Union': -- -- >>> review _This (Just "hello") :: Union Maybe '[String]@@ -220,6 +230,8 @@ -- | Lens-compatible 'Prism' for 'That'. --+-- ==== __Examples__+-- -- Use '_That' to construct a 'Union': -- -- >>> let u = This (Just "hello") :: Union Maybe '[String]@@ -296,6 +308,8 @@ -- | Case analysis for 'OpenUnion'. --+-- ==== __Examples__+-- -- Here is an example of successfully matching: -- -- >>> let string = "hello" :: String@@ -315,6 +329,8 @@ -- | This is similar to 'fromMaybe' for an 'OpenUnion'. --+-- ==== __Examples__+-- -- Here is an example of successfully matching: -- -- >>> let string = "hello" :: String@@ -360,6 +376,8 @@ -- | Just like 'unionMatch' but for 'OpenUnion'. --+-- ==== __Examples__+-- -- Successful matching: -- -- >>> let string = "hello" :: String@@ -383,6 +401,11 @@ -- containing handlers for each potential value of the 'OpenUnion'. This is -- somewhat similar to the 'Control.Exception.catches' function. --+-- When working with large 'OpenUnion's, it can be easier to use+-- 'catchesOpenUnion' than 'openUnion'.+--+-- ==== __Examples__+-- -- Here is an example of handling an 'OpenUnion' with two possible values. -- Notice that a normal tuple is used: --@@ -418,9 +441,6 @@ -- >>> let dblHandler = (\dbl -> "got a double") :: Double -> String -- >>> catchesOpenUnion dblHandler u :: String -- "got a double"------ When working with large 'OpenUnion's, it can be easier to use--- 'catchesOpenUnion' than 'openUnion'. catchesOpenUnion :: ToOpenProduct tuple (ReturnX x as) => tuple -> OpenUnion as -> x