HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Moduleservant-0.20.2Haskell2010

Servant.API.TypeLevel

This module collects utilities for manipulating servant API types. The functionality in this module is for advanced usage.

The code samples in this module use the following type synonym:

type SampleAPI = "hello" :> Get '[JSON] Int
            :<|> "bye" :> Capture "name" String :> Post '[JSON, PlainText] Bool
  • 1 type
  • 1 class
  • Packageservant-0.20.2
  • Exports17
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceTypeLevel.hs

The doctests in this module are run with following preamble:

Example12 expressions
:set -XPolyKinds:set -XGADTs:set -XTypeSynonymInstances -XFlexibleInstancesimport Data.Proxyimport Data.Type.Equalityimport Servant.APIdata OK ctx where OK :: ctx => OK ctxinstance Show (OK ctx) where show _ = "OK"let ok :: ctx => Proxy ctx -> OK ctx; ok _ = OKtype SampleAPI = "hello" :> Get '[JSON] Int :<|> "bye" :> Capture "name" String :> Post '[JSON, PlainText] Booltype FailAPI = Fragment Bool :> Fragment Int :> Get '[JSON] NoContentlet sampleAPI = Proxy :: Proxy SampleAPI

Lax inclusion

familytype family IsElem' a s :: Constraint
#

You may use this type family to tell the type checker that your custom type may be skipped as part of a link. This is useful for things like QueryParam that are optional in a URI and do not affect them if they are omitted.

Example2 expressions
data CustomThingtype instance IsElem' e (CustomThing :> s) = IsElem e s

Note that IsElem is called, which will mutually recurse back to IsElem' if it exhausts all other options again.

Once you have written a HasLink instance for CustomThing you are ready to go.

familytype family IsElem endpoint api :: Constraint where
#

Closed type family, check if endpoint is within api. Uses IsElem' if it exhausts all other options.

Example1 expression
ok (Proxy :: Proxy (IsElem ("hello" :> Get '[JSON] Int) SampleAPI))OK
Example1 expression
ok (Proxy :: Proxy (IsElem ("bye" :> Get '[JSON] Int) SampleAPI))...... Could not ......

An endpoint is considered within an api even if it is missing combinators that don't affect the URL:

Example1 expression
ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int)))OK
Example1 expression
ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (ReqBody '[JSON] Bool :> Get '[JSON] Int)))OK
  • N.B.:* IsElem a b can be seen as capturing the notion of whether the URL represented by a would match the URL represented by b, *not* whether a request represented by a matches the endpoints serving b (for the latter, use IsIn).

Equations

familytype family IsSubAPI sub api :: Constraint where
#

Check whether sub is a sub-API of api.

Example1 expression
ok (Proxy :: Proxy (IsSubAPI SampleAPI (SampleAPI :<|> Get '[JSON] Int)))OK
Example1 expression
ok (Proxy :: Proxy (IsSubAPI (SampleAPI :<|> Get '[JSON] Int) SampleAPI))...... Could not ......

This uses IsElem for checking; thus the note there applies here.

Equations

Strict inclusion

familytype family IsIn endpoint api :: Constraint where
#

Closed type family, check if endpoint is exactly within api.

Example1 expression
ok (Proxy :: Proxy (IsIn ("hello" :> Get '[JSON] Int) SampleAPI))OK

Unlike IsElem, this requires an *exact* match.

Example1 expression
ok (Proxy :: Proxy (IsIn (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int)))...... Could not ......

Equations

familytype family AllIsIn (xs :: [Type]) api :: Constraint where
#

Check that every element of xs is an endpoint of api (using IsIn).

Example1 expression
ok (Proxy :: Proxy (AllIsIn (Endpoints SampleAPI) SampleAPI))OK

Equations

Helpers

0 declarations

Lists

typetype Elem (e :: t) (es :: [t]) = ElemGo e es es
#

Check that a value is an element of a list:

Example1 expression
ok (Proxy :: Proxy (Elem Bool '[Int, Bool]))OK
Example1 expression
ok (Proxy :: Proxy (Elem String '[Int, Bool]))...... [Char]...'[Int, Bool......

Logic

familytype family Or (a :: Constraint) (b :: Constraint) :: Constraint where
#

If either a or b produce an empty constraint, produce an empty constraint.

Equations

  • Or () b = ()
  • Or a () = ()

Fragment

classclass FragmentUnique api => AtMostOneFragment api
#

If there is more than one fragment in an API endpoint, a compile-time error is raised.

Example2 expressions
type FailAPI = Fragment Bool :> Fragment Int :> Get '[JSON] NoContentinstance AtMostOneFragment FailAPI......Only one Fragment allowed per endpoint in api......
Instances3AtMostOneFragment