Skip to content

Commit

Permalink
Adding paragraph to generic cookbook
Browse files Browse the repository at this point in the history
  • Loading branch information
akhesaCaro authored and MangoIV committed Jan 27, 2025
1 parent 355dc88 commit bacdef7
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions doc/cookbook/generic/Generic.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,79 @@ case](../namedRoutes/NamedRoutes.html) cookbook that broaches the subject.

Shall we begin?

## Why would I want to use `Records` over the alternative `:<|>` operator?

With a record-based API, we don’t need to care about the declaration order of the endpoints.
For example, with the `:<|>` operator there’s room for error when the order of the API type

```haskell,ignore
type API1 = "version" :> Get '[JSON] Version
:<|> "movies" :> Get '[JSON] [Movie]
```
does not follow the `Handler` implementation order
```haskell,ignore
apiHandler :: ServerT API1 Handler
apiHandler = getMovies
:<|> getVersion
```
GHC could scold you with a very tedious message such as :
```console
• Couldn't match type 'Handler NoContent'
with 'Movie -> Handler NoContent'
Expected type: ServerT MovieCatalogAPI Handler
Actual type: Handler Version
:<|> ((Maybe SortBy -> Handler [Movie])
:<|> ((MovieId -> Handler (Maybe Movie))
:<|> ((MovieId -> Movie -> Handler NoContent)
:<|> (MovieId -> Handler NoContent))))
• In the expression:
versionHandler
:<|>
movieListHandler
:<|>
getMovieHandler :<|> updateMovieHandler :<|> deleteMovieHandler
In an equation for 'server':
server
= versionHandler
:<|>
movieListHandler
:<|>
getMovieHandler :<|> updateMovieHandler :<|> deleteMovieHandler
|
226 | server = versionHandler
```
On the contrary, with the record-based technique, we refer to the routes by their name:
```haskell,ignore
data API mode = API
{ list :: "list" :> ...
, delete :: "delete" :> ...
}
```
and GHC follows the lead :
```console
• Couldn't match type 'NoContent' with 'Movie'
Expected type: AsServerT Handler :- Delete '[JSON] Movie
Actual type: Handler NoContent
• In the 'delete' field of a record
In the expression:
MovieAPI
{get = getMovieHandler movieId,
update = updateMovieHandler movieId,
delete = deleteMovieHandler movieId}
In an equation for 'movieHandler':
movieHandler movieId
= MovieAPI
{get = getMovieHandler movieId,
update = updateMovieHandler movieId,
delete = deleteMovieHandler movieId}
|
252 | , delete = deleteMovieHandler movieId
```
So, records are more readable for a human, and GHC gives you more accurate error messages.
What are we waiting for?
```haskell
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
Expand Down

0 comments on commit bacdef7

Please sign in to comment.