{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Servant.API.Generic (
GenericMode (..),
GenericServant,
ToServant,
toServant,
fromServant,
AsApi,
ToServantApi,
genericApi,
GServantProduct,
Generic (Rep),
) where
import Data.Proxy
(Proxy (..))
import GHC.Generics
((:*:) (..), Generic (..), K1 (..), M1 (..))
import Servant.API.Alternative
type GenericServant routes mode = (GenericMode mode, Generic (routes mode), GServantProduct (Rep (routes mode)))
class GenericMode mode where
type mode :- api :: *
infixl 0 :-
type ToServant routes mode = GToServant (Rep (routes mode))
type ToServantApi routes = ToServant routes AsApi
toServant
:: GenericServant routes mode
=> routes mode -> ToServant routes mode
toServant :: forall (routes :: * -> *) mode.
GenericServant routes mode =>
routes mode -> ToServant routes mode
toServant = Rep (routes mode) Any -> GToServant (Rep (routes mode))
forall p. Rep (routes mode) p -> GToServant (Rep (routes mode))
forall (f :: * -> *) p. GServantProduct f => f p -> GToServant f
gtoServant (Rep (routes mode) Any -> GToServant (Rep (routes mode)))
-> (routes mode -> Rep (routes mode) Any)
-> routes mode
-> GToServant (Rep (routes mode))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. routes mode -> Rep (routes mode) Any
forall x. routes mode -> Rep (routes mode) x
forall a x. Generic a => a -> Rep a x
from
fromServant
:: GenericServant routes mode
=> ToServant routes mode -> routes mode
fromServant :: forall (routes :: * -> *) mode.
GenericServant routes mode =>
ToServant routes mode -> routes mode
fromServant = Rep (routes mode) Any -> routes mode
forall a x. Generic a => Rep a x -> a
forall x. Rep (routes mode) x -> routes mode
to (Rep (routes mode) Any -> routes mode)
-> (GToServant (Rep (routes mode)) -> Rep (routes mode) Any)
-> GToServant (Rep (routes mode))
-> routes mode
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GToServant (Rep (routes mode)) -> Rep (routes mode) Any
forall p. GToServant (Rep (routes mode)) -> Rep (routes mode) p
forall (f :: * -> *) p. GServantProduct f => GToServant f -> f p
gfromServant
data AsApi
instance GenericMode AsApi where
type AsApi :- api = api
genericApi
:: GenericServant routes AsApi
=> Proxy routes
-> Proxy (ToServantApi routes)
genericApi :: forall (routes :: * -> *).
GenericServant routes AsApi =>
Proxy routes -> Proxy (ToServantApi routes)
genericApi Proxy routes
_ = Proxy (GToServant (Rep (routes AsApi)))
forall {k} (t :: k). Proxy t
Proxy
class GServantProduct f where
type GToServant f
gtoServant :: f p -> GToServant f
gfromServant :: GToServant f -> f p
instance GServantProduct f => GServantProduct (M1 i c f) where
type GToServant (M1 i c f) = GToServant f
gtoServant :: forall p. M1 i c f p -> GToServant (M1 i c f)
gtoServant = f p -> GToServant f
forall p. f p -> GToServant f
forall (f :: * -> *) p. GServantProduct f => f p -> GToServant f
gtoServant (f p -> GToServant f)
-> (M1 i c f p -> f p) -> M1 i c f p -> GToServant f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. M1 i c f p -> f p
forall k i (c :: Meta) (f :: k -> *) (p :: k). M1 i c f p -> f p
unM1
gfromServant :: forall p. GToServant (M1 i c f) -> M1 i c f p
gfromServant = f p -> M1 i c f p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (f p -> M1 i c f p)
-> (GToServant f -> f p) -> GToServant f -> M1 i c f p
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GToServant f -> f p
forall p. GToServant f -> f p
forall (f :: * -> *) p. GServantProduct f => GToServant f -> f p
gfromServant
instance (GServantProduct l, GServantProduct r) => GServantProduct (l :*: r) where
type GToServant (l :*: r) = GToServant l :<|> GToServant r
gtoServant :: forall p. (:*:) l r p -> GToServant (l :*: r)
gtoServant (l p
l :*: r p
r) = l p -> GToServant l
forall p. l p -> GToServant l
forall (f :: * -> *) p. GServantProduct f => f p -> GToServant f
gtoServant l p
l GToServant l -> GToServant r -> GToServant l :<|> GToServant r
forall a b. a -> b -> a :<|> b
:<|> r p -> GToServant r
forall p. r p -> GToServant r
forall (f :: * -> *) p. GServantProduct f => f p -> GToServant f
gtoServant r p
r
gfromServant :: forall p. GToServant (l :*: r) -> (:*:) l r p
gfromServant (GToServant l
l :<|> GToServant r
r) = GToServant l -> l p
forall p. GToServant l -> l p
forall (f :: * -> *) p. GServantProduct f => GToServant f -> f p
gfromServant GToServant l
l l p -> r p -> (:*:) l r p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: GToServant r -> r p
forall p. GToServant r -> r p
forall (f :: * -> *) p. GServantProduct f => GToServant f -> f p
gfromServant GToServant r
r
instance GServantProduct (K1 i c) where
type GToServant (K1 i c) = c
gtoServant :: forall p. K1 i c p -> GToServant (K1 i c)
gtoServant = K1 i c p -> c
K1 i c p -> GToServant (K1 i c)
forall k i c (p :: k). K1 i c p -> c
unK1
gfromServant :: forall p. GToServant (K1 i c) -> K1 i c p
gfromServant = c -> K1 i c p
GToServant (K1 i c) -> K1 i c p
forall k i c (p :: k). c -> K1 i c p
K1