    {-# OPTIONS_GHC -fno-warn-orphans  #-}
    {-# LANGUAGE FlexibleContexts      #-}
    {-# LANGUAGE KindSignatures        #-}
    {-# LANGUAGE RankNTypes            #-}
    {-# LANGUAGE ScopedTypeVariables   #-}
    {-# LANGUAGE TypeFamilies          #-}
    {-# LANGUAGE TypeOperators         #-}

    module  Servant.Client.Generic (
        AsClientT,
        genericClient,
        genericClientHoist,
        ) where

    import           Data.Proxy
                     (Proxy (..))

    import           Servant.API.Generic
    import           Servant.Client.Core
    import           Servant.Client.Core.HasClient (AsClientT)

    -- | Generate a record of client functions.
    genericClient
        :: forall routes m.
           ( HasClient m (ToServantApi routes)
           , GenericServant routes (AsClientT m)
           , Client m (ToServantApi routes) ~ ToServant routes (AsClientT m)
           )
        => routes (AsClientT m)
    genericClient :: forall (routes :: Type -> Type) (m :: Type -> Type).
    (HasClient m (ToServantApi routes),
     GenericServant routes (AsClientT m),
     Client m (ToServantApi routes) ~ ToServant routes (AsClientT m)) =>
    routes (AsClientT m)
    genericClient
        = ToServant routes (AsClientT m) -> routes (AsClientT m)
    forall {k} (routes :: k -> Type) (mode :: k).
    GenericServant routes mode =>
    ToServant routes mode -> routes mode
    fromServant
        (ToServant routes (AsClientT m) -> routes (AsClientT m))
    -> ToServant routes (AsClientT m) -> routes (AsClientT m)
    forall a b. (a -> b) -> a -> b
    $ Proxy (ToServantApi routes)
    -> Proxy m -> Client m (ToServantApi routes)
    forall (m :: Type -> Type) api.
    HasClient m api =>
    Proxy api -> Proxy m -> Client m api
    clientIn (Proxy (ToServantApi routes)
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy (ToServantApi routes)) (Proxy m
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy m)

    -- | 'genericClient' but with 'hoistClientMonad' in between.
    genericClientHoist
        :: forall routes m n.
           ( HasClient m (ToServantApi routes)
           , GenericServant routes (AsClientT n)
           , Client n (ToServantApi routes) ~ ToServant routes (AsClientT n)
           )
        => (forall x. m x -> n x)  -- ^ natural transformation
        -> routes (AsClientT n)
    genericClientHoist :: forall (routes :: Type -> Type) (m :: Type -> Type)
           (n :: Type -> Type).
    (HasClient m (ToServantApi routes),
     GenericServant routes (AsClientT n),
     Client n (ToServantApi routes) ~ ToServant routes (AsClientT n)) =>
    (forall x. m x -> n x) -> routes (AsClientT n)
    genericClientHoist forall x. m x -> n x
    nt
        = ToServant routes (AsClientT n) -> routes (AsClientT n)
    forall {k} (routes :: k -> Type) (mode :: k).
    GenericServant routes mode =>
    ToServant routes mode -> routes mode
    fromServant
        (ToServant routes (AsClientT n) -> routes (AsClientT n))
    -> ToServant routes (AsClientT n) -> routes (AsClientT n)
    forall a b. (a -> b) -> a -> b
    $ Proxy m
    -> Proxy (ToServantApi routes)
    -> (forall x. m x -> n x)
    -> Client m (ToServantApi routes)
    -> Client n (ToServantApi routes)
    forall (m :: Type -> Type) api (mon :: Type -> Type)
           (mon' :: Type -> Type).
    HasClient m api =>
    Proxy m
    -> Proxy api
    -> (forall x. mon x -> mon' x)
    -> Client mon api
    -> Client mon' api
    forall (mon :: Type -> Type) (mon' :: Type -> Type).
    Proxy m
    -> Proxy (ToServantApi routes)
    -> (forall x. mon x -> mon' x)
    -> Client mon (ToServantApi routes)
    -> Client mon' (ToServantApi routes)
    hoistClientMonad Proxy m
    m Proxy (ToServantApi routes)
    api m x -> n x
    forall x. m x -> n x
    nt
        (Client m (ToServantApi routes) -> Client n (ToServantApi routes))
    -> Client m (ToServantApi routes) -> Client n (ToServantApi routes)
    forall a b. (a -> b) -> a -> b
    $ Proxy (ToServantApi routes)
    -> Proxy m -> Client m (ToServantApi routes)
    forall (m :: Type -> Type) api.
    HasClient m api =>
    Proxy api -> Proxy m -> Client m api
    clientIn Proxy (ToServantApi routes)
    api Proxy m
    m
      where
        m :: Proxy m
    m = Proxy m
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy m
        api :: Proxy (ToServantApi routes)
    api = Proxy (ToServantApi routes)
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy (ToServantApi routes)