Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pick up PR for named routes cookbook again #1726

Merged
merged 15 commits into from
Feb 18, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
why paragraph, gone
akhesaCaro authored and MangoIV committed Jan 27, 2025
commit 355dc88476b2e986f3e8db26b7d1c1791146e3e5
81 changes: 0 additions & 81 deletions doc/cookbook/namedRoutes/NamedRoutes.lhs
Original file line number Diff line number Diff line change
@@ -20,87 +20,6 @@ However, it should be understood that this cookbook does _not_ dwell on the
built-in servant combinators as the [Structuring APIs
](<../structuring-apis/StructuringApis.html>) cookbook already covers that angle.

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

With `NamedRoutes`, 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 `NamedRoutes` 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, NamedRoutes is more readable for a human, and GHC gives you more accurate error messages.

What are we waiting for?


## Boilerplate time!