Move `HasServer (NamedRoutes routes)` instance
The instance has been moved to `Servant.Server.Internal`, as the
instances for other combinators. It is necessary so that the instance
can be re-exported from `Servant.Server` without circular imports.
Otherwise, users have to import `Servant.Server.Generic` manually ;
forgetting to do so will produce confusing error messages about the
missing instance.
Move `HasClient (NamedRoutes routes)` instance
Moved so that the instance is made available when importing
`Servant.Client`, avoiding possibly confusing errors when
`Servant.Client.Generic` isn't imported.
QuantifiedConstraints isn't available for GHC 8.4 (where our GHCJS
version is still stuck).
We may need to take a drastic decision for GHCJS at some point.
We define `ServerT (NamedRoutes api) m` as `api (AsServerT m)`, so that
the server of an record-defined API is a record of handlers.
The implementation piggy backs on the instance for “vanilla” servant
types with `(:<|>)`, using the `GServantProduct` for converting backd
and forth between the record / vanilla servers.
The main difficulty is that GHC needs to know that this operation is
legit, which can be expressed as the fact that:
```
GToServant (Rep (ServerT (NamedRoutes api))) m ~
ServerT (GToServant (Rep (api AsApi))) m
```
plus a few additional constraints.
This is easy enough for `route`, as we know that `m ~ Handler`. But in
the case of `hoistServerWithContext`, the two involved monads are
unknown ; in other words, this constraint needs to hold `forall m.`
Switching `-XQuantifiedConstraints` on is not sufficient, as our
constraints involve type families (`Rep` and `ServerT`). Our trick is to
use an intermediary typeclass, `GServer`, as a provider of evidence (in
the form of a `Dict`) that our constraints are indeed satisfied for a
particular monad.
The only instance of `GServer` is defined along with it, so it is
practically invisible to users.
Allows users to directly embed APIs defined as records of routes into
vanilla Servant API types.
E.g.:
```haskell
data MyRoutes mode = MyRoutes
{ version :: mode :- Get '[JSON] Int
, …
}
type API = "prefix" :> NamedRoutes MyRoutes :<|> …
```
APIs can thus be recursively defined directly with Generic record types.
ServerError field errBody uses ByteString, whose IsString instance kills
Unicode, thus turning example into garbage. Changed it to simple ASCII
string, since Unicode art did not exactly correspond to 404 error
anyway.
Fixes#1371
This allows us to deprecate GHCJS 8.4 (which makes sense, as vanilla GHC
< 8.6 is already deprecated).
We re-use GHCJS from reflex-platform, which unfortunately isn't
up-to-date with latest GHC and is only 8.6. The benefit of using
reflex-platform is that it provides nix expressions for GHCJS + a binary
nix cache.
reflex-platform patches text to use a JS-String based internal
representation for performance reasons, so we provide a few haskell
dependencies from reflex-platform as well:
- hashable
- attoparsec
As those rely on text's internal representation but have been patched
for reflex-platform.