put some consistency between NamedRoutes cookbook and Generic cookbook
This commit is contained in:
parent
ece559ee6e
commit
19e432c33e
|
@ -1,4 +1,14 @@
|
||||||
# Using generics
|
# Record-based APIs: the simple case
|
||||||
|
|
||||||
|
This cookbook explains how to implement an API with a simple record-based
|
||||||
|
structure. We only deal with non-nested APIs in which every endpoint is on the same
|
||||||
|
level.
|
||||||
|
|
||||||
|
If a you need nesting because you have different branches in your API tree, you
|
||||||
|
might want to jump directly to the [Record-based APIs: the nested records
|
||||||
|
case](../namedRoutes/NamedRoutes.html) cookbook that broaches the subject.
|
||||||
|
|
||||||
|
Shall we begin?
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
@ -110,7 +120,7 @@ main = do
|
||||||
_ -> putStrLn "To run, pass 'run' argument: cabal new-run cookbook-generic run"
|
_ -> putStrLn "To run, pass 'run' argument: cabal new-run cookbook-generic run"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using generics together with a custom monad
|
## Using record-based APIs together with a custom monad
|
||||||
|
|
||||||
If your app uses a custom monad, here's how you can combine it with
|
If your app uses a custom monad, here's how you can combine it with
|
||||||
generics.
|
generics.
|
||||||
|
@ -121,9 +131,6 @@ data AppCustomState =
|
||||||
|
|
||||||
type AppM = ReaderT AppCustomState Handler
|
type AppM = ReaderT AppCustomState Handler
|
||||||
|
|
||||||
apiMyMonad :: Proxy (ToServantApi Routes)
|
|
||||||
apiMyMonad = genericApi (Proxy :: Proxy Routes)
|
|
||||||
|
|
||||||
getRouteMyMonad :: Int -> AppM String
|
getRouteMyMonad :: Int -> AppM String
|
||||||
getRouteMyMonad = return . show
|
getRouteMyMonad = return . show
|
||||||
|
|
||||||
|
@ -139,3 +146,4 @@ nt s x = runReaderT x s
|
||||||
|
|
||||||
appMyMonad :: AppCustomState -> Application
|
appMyMonad :: AppCustomState -> Application
|
||||||
appMyMonad state = genericServeT (nt state) recordMyMonad
|
appMyMonad state = genericServeT (nt state) recordMyMonad
|
||||||
|
```
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
# NamedRoutes - Using records to define APIs
|
# Record-based APIs: the nested records case
|
||||||
|
|
||||||
*Available in Servant 0.19 or higher*
|
*Available in Servant 0.19 or higher*
|
||||||
|
|
||||||
Servant offers a very natural way of constructing APIs with nested records, called `NamedRoutes`.
|
Servant offers a very natural way of constructing APIs with nested records, called `NamedRoutes`.
|
||||||
|
|
||||||
This cookbook explains how to implement such nested-record-APIs using `NamedRoutes` through the example of a Movie Catalog.
|
This cookbook explains how to implement such nested-record-based-APIs using
|
||||||
|
`NamedRoutes` through the example of a Movie Catalog.
|
||||||
|
If you don't need the nested aspect of the record-based API, you might want to look at [Record-based
|
||||||
|
APIs: the simple
|
||||||
|
case](../generic/Generic.html) cookbook
|
||||||
|
which covers a simpler implementation in which every endpoint is on the same
|
||||||
|
level.
|
||||||
|
|
||||||
First, we start by constructing the domain types of our Movie Catalog.
|
First, we start by constructing the domain types of our Movie Catalog.
|
||||||
After, we show you how to implement the API type with the NamedRoutes records.
|
After, we show you how to implement the API type with the NamedRoutes records.
|
||||||
|
|
|
@ -35,6 +35,11 @@ The first part, `FactoringAPI`, shows how we can
|
||||||
endpoints, just like we turn `a * b + a * c` into
|
endpoints, just like we turn `a * b + a * c` into
|
||||||
`a * (b + c)` in algebra.
|
`a * (b + c)` in algebra.
|
||||||
|
|
||||||
|
(It should be noted that the `(:<|>)` operator is not the only way of combining
|
||||||
|
endpoints with Servant. Other techniques are shown in subsequent cookbooks. See
|
||||||
|
[record-based alternative for implementing APIs](StructuringApis.html#record-based-alternative-for-implementing-apis))
|
||||||
|
|
||||||
|
|
||||||
``` haskell
|
``` haskell
|
||||||
-- Two endpoints:
|
-- Two endpoints:
|
||||||
-- - GET /x/<some 'Int'>[?y=<some 'Int'>]
|
-- - GET /x/<some 'Int'>[?y=<some 'Int'>]
|
||||||
|
@ -203,3 +208,14 @@ main = run 8080 . serve api $
|
||||||
|
|
||||||
This program is available as a cabal project
|
This program is available as a cabal project
|
||||||
[here](https://github.com/haskell-servant/servant/tree/master/doc/cookbook/structuring-apis).
|
[here](https://github.com/haskell-servant/servant/tree/master/doc/cookbook/structuring-apis).
|
||||||
|
|
||||||
|
## Record-based alternative for implementing APIs
|
||||||
|
|
||||||
|
It should be noted that the `(:<|>)` is not the only way of combining endpoints.
|
||||||
|
Servant offers a convenient way to design APIs with records avoiding the ordering constraint of the operator.
|
||||||
|
|
||||||
|
A simple case is approached in the [Record-based APIs: the simple
|
||||||
|
case](../generic/Generic.html)
|
||||||
|
cookbook, which deals with flat APIs where every endpoint is on the same level.
|
||||||
|
Also, a more complex example with nested record is discussed in [Record-based APIs: the nested
|
||||||
|
records case](../namedRoutes/NamedRoutes.html) in which we implement an API tree with many branches.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user