{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Servant.Generic
( (:-)
, AsServerT
, AsServer
, AsApi
, AsLink
, ToServant
, toServant
, fromServant
, GenericProduct
, GProduct(..)
, Generic(..)
, fieldLink
) where
import GHC.Generics
import Servant
class GProduct f where
type GToServant f
gtoServant :: f p -> GToServant f
gfromServant :: GToServant f -> f p
instance GProduct f => GProduct (M1 i c f) where
type GToServant (M1 i c f) = GToServant f
gtoServant (M1 x) = gtoServant x
gfromServant x = M1 (gfromServant x)
instance (GProduct l, GProduct r) => GProduct (l :*: r) where
type GToServant (l :*: r) = GToServant l :<|> GToServant r
gtoServant (l :*: r) = gtoServant l :<|> gtoServant r
gfromServant (l :<|> r) = gfromServant l :*: gfromServant r
instance GProduct (K1 i c) where
type GToServant (K1 i c) = c
gtoServant (K1 x) = x
gfromServant x = K1 x
type GenericProduct a = (Generic a, GProduct (Rep a))
type ToServant a = GToServant (Rep a)
toServant :: GenericProduct a => a -> ToServant a
toServant = gtoServant . from
fromServant :: GenericProduct a => ToServant a -> a
fromServant = to . gfromServant
type family mode :- api
infixl 3 :-
data AsApi
type instance AsApi :- api = api
data AsLink
#if MIN_VERSION_servant(0,14,0)
type instance AsLink :- api = MkLink api Link
#else
type instance AsLink :- api = MkLink api
#endif
data AsServerT (m :: * -> *)
type instance AsServerT m :- api = ServerT api m
type AsServer = AsServerT Handler
fieldLink :: forall routes endpoint. (IsElem endpoint (ToServant (routes AsApi)), HasLink endpoint)
=> (routes AsApi -> endpoint)
#if MIN_VERSION_servant(0,14,0)
-> MkLink endpoint Link
#else
-> MkLink endpoint
#endif
fieldLink _ = safeLink (Proxy :: Proxy (ToServant (routes AsApi))) (Proxy :: Proxy endpoint)