{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE EmptyCase #-}
module Servant.API.MultiVerb
(
MultiVerb,
MultiVerb1,
Respond,
RespondAs,
RespondEmpty,
RespondStreaming,
WithHeaders,
DescHeader,
OptHeader,
AsHeaders (..),
ServantHeaders(..),
ServantHeader(..),
AsUnion (..),
eitherToUnion,
eitherFromUnion,
maybeToUnion,
maybeFromUnion,
AsConstructor (..),
GenericAsConstructor (..),
GenericAsUnion (..),
ResponseType,
ResponseTypes,
UnrenderResult(..),
) where
import Control.Applicative (Alternative(..), empty)
import Control.Monad (ap, MonadPlus(..))
import Data.ByteString (ByteString)
import Data.Kind
import Data.Proxy
import Data.SOP
import Data.Sequence (Seq(..))
import GHC.TypeLits
import Generics.SOP as GSOP
import Network.HTTP.Types as HTTP
import Web.HttpApiData (FromHttpApiData, ToHttpApiData, parseHeader, toHeader)
import qualified Data.CaseInsensitive as CI
import qualified Data.Sequence as Seq
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import Servant.API.TypeLevel.List
import Servant.API.Stream (SourceIO)
import Servant.API.UVerb.Union (Union)
import Servant.API.Header (Header')
data Respond (s :: Nat) (description :: Symbol) (a :: Type)
data RespondAs responseContentType (s :: Nat) (description :: Symbol) (a :: Type)
type RespondEmpty s description = RespondAs '() s description ()
data RespondStreaming (s :: Nat) (description :: Symbol) (framing :: Type) (ct :: Type)
data UnrenderResult a = StatusMismatch | UnrenderError String | UnrenderSuccess a
deriving (UnrenderResult a -> UnrenderResult a -> Bool
(UnrenderResult a -> UnrenderResult a -> Bool)
-> (UnrenderResult a -> UnrenderResult a -> Bool)
-> Eq (UnrenderResult a)
forall a. Eq a => UnrenderResult a -> UnrenderResult a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => UnrenderResult a -> UnrenderResult a -> Bool
== :: UnrenderResult a -> UnrenderResult a -> Bool
$c/= :: forall a. Eq a => UnrenderResult a -> UnrenderResult a -> Bool
/= :: UnrenderResult a -> UnrenderResult a -> Bool
Eq, Int -> UnrenderResult a -> ShowS
[UnrenderResult a] -> ShowS
UnrenderResult a -> String
(Int -> UnrenderResult a -> ShowS)
-> (UnrenderResult a -> String)
-> ([UnrenderResult a] -> ShowS)
-> Show (UnrenderResult a)
forall a. Show a => Int -> UnrenderResult a -> ShowS
forall a. Show a => [UnrenderResult a] -> ShowS
forall a. Show a => UnrenderResult a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> UnrenderResult a -> ShowS
showsPrec :: Int -> UnrenderResult a -> ShowS
$cshow :: forall a. Show a => UnrenderResult a -> String
show :: UnrenderResult a -> String
$cshowList :: forall a. Show a => [UnrenderResult a] -> ShowS
showList :: [UnrenderResult a] -> ShowS
Show, (forall a b. (a -> b) -> UnrenderResult a -> UnrenderResult b)
-> (forall a b. a -> UnrenderResult b -> UnrenderResult a)
-> Functor UnrenderResult
forall a b. a -> UnrenderResult b -> UnrenderResult a
forall a b. (a -> b) -> UnrenderResult a -> UnrenderResult b
forall (f :: Type -> Type).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> UnrenderResult a -> UnrenderResult b
fmap :: forall a b. (a -> b) -> UnrenderResult a -> UnrenderResult b
$c<$ :: forall a b. a -> UnrenderResult b -> UnrenderResult a
<$ :: forall a b. a -> UnrenderResult b -> UnrenderResult a
Functor)
instance Applicative UnrenderResult where
pure :: forall a. a -> UnrenderResult a
pure = a -> UnrenderResult a
forall a. a -> UnrenderResult a
UnrenderSuccess
<*> :: forall a b.
UnrenderResult (a -> b) -> UnrenderResult a -> UnrenderResult b
(<*>) = UnrenderResult (a -> b) -> UnrenderResult a -> UnrenderResult b
forall (m :: Type -> Type) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad UnrenderResult where
return :: forall a. a -> UnrenderResult a
return = a -> UnrenderResult a
forall a. a -> UnrenderResult a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure
UnrenderResult a
StatusMismatch >>= :: forall a b.
UnrenderResult a -> (a -> UnrenderResult b) -> UnrenderResult b
>>= a -> UnrenderResult b
_ = UnrenderResult b
forall a. UnrenderResult a
StatusMismatch
UnrenderError String
e >>= a -> UnrenderResult b
_ = String -> UnrenderResult b
forall a. String -> UnrenderResult a
UnrenderError String
e
UnrenderSuccess a
x >>= a -> UnrenderResult b
f = a -> UnrenderResult b
f a
x
instance Alternative UnrenderResult where
empty :: forall a. UnrenderResult a
empty = UnrenderResult a
forall a. UnrenderResult a
forall (m :: Type -> Type) a. MonadPlus m => m a
mzero
<|> :: forall a. UnrenderResult a -> UnrenderResult a -> UnrenderResult a
(<|>) = UnrenderResult a -> UnrenderResult a -> UnrenderResult a
forall a. UnrenderResult a -> UnrenderResult a -> UnrenderResult a
forall (m :: Type -> Type) a. MonadPlus m => m a -> m a -> m a
mplus
instance MonadPlus UnrenderResult where
mzero :: forall a. UnrenderResult a
mzero = UnrenderResult a
forall a. UnrenderResult a
StatusMismatch
mplus :: forall a. UnrenderResult a -> UnrenderResult a -> UnrenderResult a
mplus UnrenderResult a
StatusMismatch UnrenderResult a
m = UnrenderResult a
m
mplus (UnrenderError String
e) UnrenderResult a
StatusMismatch = String -> UnrenderResult a
forall a. String -> UnrenderResult a
UnrenderError String
e
mplus (UnrenderError String
_) UnrenderResult a
m = UnrenderResult a
m
mplus m :: UnrenderResult a
m@(UnrenderSuccess a
_) UnrenderResult a
_ = UnrenderResult a
m
type family ResponseType a :: Type
type instance ResponseType (Respond s description a) = a
type instance ResponseType (RespondAs responseContentType s description a) = a
type instance ResponseType (RespondStreaming s description framing ct) = SourceIO ByteString
data (headers :: [Type]) (returnType :: Type) (response :: Type)
class headers response returnType where
:: (NP I headers, response) -> returnType
:: returnType -> (NP I headers, response)
instance AsHeaders '[a] () a where
toHeaders :: a -> (NP I '[a], ())
toHeaders a
a = (a -> I a
forall a. a -> I a
I a
a I a -> NP I '[] -> NP I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil, ())
fromHeaders :: (NP I '[a], ()) -> a
fromHeaders = I a -> a
forall a. I a -> a
unI (I a -> a) -> ((NP I '[a], ()) -> I a) -> (NP I '[a], ()) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NP I '[a] -> I a
forall {k} (f :: k -> Type) (x :: k) (xs :: [k]).
NP f (x : xs) -> f x
hd (NP I '[a] -> I a)
-> ((NP I '[a], ()) -> NP I '[a]) -> (NP I '[a], ()) -> I a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NP I '[a], ()) -> NP I '[a]
forall a b. (a, b) -> a
fst
instance AsHeaders '[h] a (a, h) where
toHeaders :: (a, h) -> (NP I '[h], a)
toHeaders (a
t, h
cc) = (h -> I h
forall a. a -> I a
I h
cc I h -> NP I '[] -> NP I '[h]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil, a
t)
fromHeaders :: (NP I '[h], a) -> (a, h)
fromHeaders (I x
cc :* NP I xs
Nil, a
t) = (a
t, h
x
cc)
instance AsHeaders '[a, b] () (a, b) where
toHeaders :: (a, b) -> (NP I '[a, b], ())
toHeaders (a
h1, b
h2) = (a -> I a
forall a. a -> I a
I a
h1 I a -> NP I '[b] -> NP I '[a, b]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* b -> I b
forall a. a -> I a
I b
h2 I b -> NP I '[] -> NP I '[b]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil, ())
fromHeaders :: (NP I '[a, b], ()) -> (a, b)
fromHeaders (I x
h1 :* I x
h2 :* NP I xs
Nil, ()) = (a
x
h1, b
x
h2)
data (name :: Symbol) (description :: Symbol) (a :: Type)
data h
class headers xs | headers -> xs where
:: NP I xs -> [HTTP.Header]
:: Seq HTTP.Header -> Maybe (NP I xs)
instance ServantHeaders '[] '[] where
constructHeaders :: NP I '[] -> [Header]
constructHeaders NP I '[]
Nil = []
extractHeaders :: Seq Header -> Maybe (NP I '[])
extractHeaders Seq Header
_ = NP I '[] -> Maybe (NP I '[])
forall a. a -> Maybe a
Just NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil
headerName :: forall name. (KnownSymbol name) => HTTP.HeaderName
=
ByteString -> HeaderName
forall s. FoldCase s => s -> CI s
CI.mk
(ByteString -> HeaderName)
-> (String -> ByteString) -> String -> HeaderName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8
(Text -> ByteString) -> (String -> Text) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack
(String -> HeaderName) -> String -> HeaderName
forall a b. (a -> b) -> a -> b
$ Proxy name -> String
forall (n :: Symbol) (proxy :: Symbol -> Type).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @name)
instance
( KnownSymbol name,
ServantHeader h name x,
FromHttpApiData x,
ServantHeaders headers xs
) =>
ServantHeaders (h ': headers) (x ': xs)
where
constructHeaders :: NP I (x : xs) -> [Header]
constructHeaders (I x
x :* NP I xs
xs) =
forall (h :: a) (name :: Symbol) x.
ServantHeader h name x =>
x -> [Header]
forall {k} (h :: k) (name :: Symbol) x.
ServantHeader h name x =>
x -> [Header]
constructHeader @h x
x
[Header] -> [Header] -> [Header]
forall a. Semigroup a => a -> a -> a
<> forall (headers :: [a]) (xs :: [Type]).
ServantHeaders headers xs =>
NP I xs -> [Header]
forall {k} (headers :: k) (xs :: [Type]).
ServantHeaders headers xs =>
NP I xs -> [Header]
constructHeaders @headers NP I xs
xs
extractHeaders :: Seq Header -> Maybe (NP I (x : xs))
extractHeaders Seq Header
headers = do
let name' :: HeaderName
name' = forall (name :: Symbol). KnownSymbol name => HeaderName
headerName @name
(Seq Header
headers0, Seq Header
headers1) = (Header -> Bool) -> Seq Header -> (Seq Header, Seq Header)
forall a. (a -> Bool) -> Seq a -> (Seq a, Seq a)
Seq.partition (\(HeaderName
h, ByteString
_) -> HeaderName
h HeaderName -> HeaderName -> Bool
forall a. Eq a => a -> a -> Bool
== HeaderName
name') Seq Header
headers
x
x <- case Seq Header
headers0 of
Seq Header
Seq.Empty -> Maybe x
forall a. Maybe a
forall (f :: Type -> Type) a. Alternative f => f a
empty
((HeaderName
_, ByteString
h) :<| Seq Header
_) -> (Text -> Maybe x) -> (x -> Maybe x) -> Either Text x -> Maybe x
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe x -> Text -> Maybe x
forall a b. a -> b -> a
const Maybe x
forall a. Maybe a
forall (f :: Type -> Type) a. Alternative f => f a
empty) x -> Maybe x
forall a. a -> Maybe a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ByteString -> Either Text x
forall a. FromHttpApiData a => ByteString -> Either Text a
parseHeader ByteString
h)
NP I xs
xs <- forall (headers :: [a]) (xs :: [Type]).
ServantHeaders headers xs =>
Seq Header -> Maybe (NP I xs)
forall {k} (headers :: k) (xs :: [Type]).
ServantHeaders headers xs =>
Seq Header -> Maybe (NP I xs)
extractHeaders @headers Seq Header
headers1
pure (x -> I x
forall a. a -> I a
I x
x I x -> NP I xs -> NP I (x : xs)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I xs
xs)
class h (name :: Symbol) x | h -> name x where
:: x -> [HTTP.Header]
instance
(KnownSymbol name, ToHttpApiData x) =>
ServantHeader (Header' mods name x) name x
where
constructHeader :: x -> [Header]
constructHeader x
x = [(forall (name :: Symbol). KnownSymbol name => HeaderName
headerName @name, x -> ByteString
forall a. ToHttpApiData a => a -> ByteString
toHeader x
x)]
instance
(KnownSymbol name, ToHttpApiData x) =>
ServantHeader (DescHeader name description x) name x
where
constructHeader :: x -> [Header]
constructHeader x
x = [(forall (name :: Symbol). KnownSymbol name => HeaderName
headerName @name, x -> ByteString
forall a. ToHttpApiData a => a -> ByteString
toHeader x
x)]
instance (ServantHeader h name x) => ServantHeader (OptHeader h) name (Maybe x) where
constructHeader :: Maybe x -> [Header]
constructHeader = (x -> [Header]) -> Maybe x -> [Header]
forall m a. Monoid m => (a -> m) -> Maybe a -> m
forall (t :: Type -> Type) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (forall (h :: k) (name :: Symbol) x.
ServantHeader h name x =>
x -> [Header]
forall {k} (h :: k) (name :: Symbol) x.
ServantHeader h name x =>
x -> [Header]
constructHeader @h)
type instance ResponseType (WithHeaders headers returnType response) = returnType
type family ResponseTypes (as :: [Type]) where
ResponseTypes '[] = '[]
ResponseTypes (a ': as) = ResponseType a ': ResponseTypes as
data MultiVerb (method :: StdMethod) requestMimeTypes (as :: [Type]) (responses :: Type)
type MultiVerb1 method requestMimeTypes a = MultiVerb method requestMimeTypes '[a] (ResponseType a)
class AsUnion (as :: [Type]) (r :: Type) where
toUnion :: r -> Union (ResponseTypes as)
fromUnion :: Union (ResponseTypes as) -> r
instance (rs ~ ResponseTypes as) => AsUnion as (Union rs) where
toUnion :: Union rs -> Union (ResponseTypes as)
toUnion = Union rs -> Union rs
Union rs -> Union (ResponseTypes as)
forall a. a -> a
id
fromUnion :: Union (ResponseTypes as) -> Union rs
fromUnion = Union rs -> Union rs
Union (ResponseTypes as) -> Union rs
forall a. a -> a
id
instance (ResponseType r ~ a) => AsUnion '[r] a where
toUnion :: a -> Union (ResponseTypes '[r])
toUnion = I a -> NS I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (I a -> NS I '[a]) -> (a -> I a) -> a -> NS I '[a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> I a
forall a. a -> I a
I
fromUnion :: Union (ResponseTypes '[r]) -> a
fromUnion = I a -> a
forall a. I a -> a
unI (I a -> a) -> (NS I '[a] -> I a) -> NS I '[a] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NS I '[a] -> I a
forall {k} (f :: k -> Type) (x :: k). NS f '[x] -> f x
unZ
_foo :: Union '[Int]
_foo :: Union '[Int]
_foo = forall (as :: [Type]) r.
AsUnion as r =>
r -> Union (ResponseTypes as)
toUnion @'[Respond 200 "test" Int] @Int Int
3
class InjectAfter as bs where
injectAfter :: Union bs -> Union (as .++ bs)
instance InjectAfter '[] bs where
injectAfter :: Union bs -> Union ('[] .++ bs)
injectAfter = Union bs -> Union bs
Union bs -> Union ('[] .++ bs)
forall a. a -> a
id
instance (InjectAfter as bs) => InjectAfter (a ': as) bs where
injectAfter :: Union bs -> Union ((a : as) .++ bs)
injectAfter = NS I (as .++ bs) -> NS I (a : (as .++ bs))
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (NS I (as .++ bs) -> NS I (a : (as .++ bs)))
-> (Union bs -> NS I (as .++ bs))
-> Union bs
-> NS I (a : (as .++ bs))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (as :: [Type]) (bs :: [Type]).
InjectAfter as bs =>
Union bs -> Union (as .++ bs)
injectAfter @as @bs
class InjectBefore as bs where
injectBefore :: Union as -> Union (as .++ bs)
instance InjectBefore '[] bs where
injectBefore :: Union '[] -> Union ('[] .++ bs)
injectBefore Union '[]
x = case Union '[]
x of {}
instance (InjectBefore as bs) => InjectBefore (a ': as) bs where
injectBefore :: Union (a : as) -> Union ((a : as) .++ bs)
injectBefore (Z I x
x) = I x -> NS I (x : (as .++ bs))
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z I x
x
injectBefore (S NS I xs
x) = NS I (as .++ bs) -> NS I (a : (as .++ bs))
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (forall (as :: [Type]) (bs :: [Type]).
InjectBefore as bs =>
Union as -> Union (as .++ bs)
injectBefore @as @bs Union as
NS I xs
x)
eitherToUnion ::
forall as bs a b.
(InjectAfter as bs, InjectBefore as bs) =>
(a -> Union as) ->
(b -> Union bs) ->
(Either a b -> Union (as .++ bs))
eitherToUnion :: forall (as :: [Type]) (bs :: [Type]) a b.
(InjectAfter as bs, InjectBefore as bs) =>
(a -> Union as)
-> (b -> Union bs) -> Either a b -> Union (as .++ bs)
eitherToUnion a -> Union as
f b -> Union bs
_ (Left a
a) = forall (as :: [Type]) (bs :: [Type]).
InjectBefore as bs =>
Union as -> Union (as .++ bs)
injectBefore @as @bs (a -> Union as
f a
a)
eitherToUnion a -> Union as
_ b -> Union bs
g (Right b
b) = forall (as :: [Type]) (bs :: [Type]).
InjectAfter as bs =>
Union bs -> Union (as .++ bs)
injectAfter @as @bs (b -> Union bs
g b
b)
class EitherFromUnion as bs where
eitherFromUnion ::
(Union as -> a) ->
(Union bs -> b) ->
(Union (as .++ bs) -> Either a b)
instance EitherFromUnion '[] bs where
eitherFromUnion :: forall a b.
(Union '[] -> a)
-> (Union bs -> b) -> Union ('[] .++ bs) -> Either a b
eitherFromUnion Union '[] -> a
_ Union bs -> b
g = b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> (Union bs -> b) -> Union bs -> Either a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Union bs -> b
g
instance (EitherFromUnion as bs) => EitherFromUnion (a ': as) bs where
eitherFromUnion :: forall a b.
(Union (a : as) -> a)
-> (Union bs -> b) -> Union ((a : as) .++ bs) -> Either a b
eitherFromUnion Union (a : as) -> a
f Union bs -> b
_ (Z I x
x) = a -> Either a b
forall a b. a -> Either a b
Left (Union (a : as) -> a
f (I a -> Union (a : as)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z I a
I x
x))
eitherFromUnion Union (a : as) -> a
f Union bs -> b
g (S NS I xs
x) = forall (as :: [Type]) (bs :: [Type]) a b.
EitherFromUnion as bs =>
(Union as -> a)
-> (Union bs -> b) -> Union (as .++ bs) -> Either a b
eitherFromUnion @as @bs (Union (a : as) -> a
f (Union (a : as) -> a)
-> (Union as -> Union (a : as)) -> Union as -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Union as -> Union (a : as)
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S) Union bs -> b
g NS I xs
Union (as .++ bs)
x
maybeToUnion ::
forall as a.
(InjectAfter as '[()], InjectBefore as '[()]) =>
(a -> Union as) ->
(Maybe a -> Union (as .++ '[()]))
maybeToUnion :: forall (as :: [Type]) a.
(InjectAfter as '[()], InjectBefore as '[()]) =>
(a -> Union as) -> Maybe a -> Union (as .++ '[()])
maybeToUnion a -> Union as
f (Just a
a) = forall (as :: [Type]) (bs :: [Type]).
InjectBefore as bs =>
Union as -> Union (as .++ bs)
injectBefore @as @'[()] (a -> Union as
f a
a)
maybeToUnion a -> Union as
_ Maybe a
Nothing = forall (as :: [Type]) (bs :: [Type]).
InjectAfter as bs =>
Union bs -> Union (as .++ bs)
injectAfter @as @'[()] (I () -> Union '[()]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (() -> I ()
forall a. a -> I a
I ()))
maybeFromUnion ::
forall as a.
(EitherFromUnion as '[()]) =>
(Union as -> a) ->
(Union (as .++ '[()]) -> Maybe a)
maybeFromUnion :: forall (as :: [Type]) a.
EitherFromUnion as '[()] =>
(Union as -> a) -> Union (as .++ '[()]) -> Maybe a
maybeFromUnion Union as -> a
f =
Either a (NS I (() : Any)) -> Maybe a
forall {a} {b}. Either a b -> Maybe a
leftToMaybe (Either a (NS I (() : Any)) -> Maybe a)
-> (Union (as .++ '[()]) -> Either a (NS I (() : Any)))
-> Union (as .++ '[()])
-> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (as :: [Type]) (bs :: [Type]) a b.
EitherFromUnion as bs =>
(Union as -> a)
-> (Union bs -> b) -> Union (as .++ bs) -> Either a b
eitherFromUnion @as @'[()] Union as -> a
f (NS I (() : Any) -> Union '[()] -> NS I (() : Any)
forall a b. a -> b -> a
const (I () -> NS I (() : Any)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (() -> I ()
forall a. a -> I a
I ())))
where
leftToMaybe :: Either a b -> Maybe a
leftToMaybe = (a -> Maybe a) -> (b -> Maybe a) -> Either a b -> Maybe a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> Maybe a
forall a. a -> Maybe a
Just (Maybe a -> b -> Maybe a
forall a b. a -> b -> a
const Maybe a
forall a. Maybe a
Nothing)
class AsConstructor xs r where
toConstructor :: ResponseType r -> NP I xs
fromConstructor :: NP I xs -> ResponseType r
class AsConstructors xss rs where
toSOP :: Union (ResponseTypes rs) -> SOP I xss
fromSOP :: SOP I xss -> Union (ResponseTypes rs)
instance AsConstructors '[] '[] where
toSOP :: Union (ResponseTypes '[]) -> SOP I '[]
toSOP Union (ResponseTypes '[])
x = case Union (ResponseTypes '[])
x of {}
fromSOP :: SOP I '[] -> Union (ResponseTypes '[])
fromSOP SOP I '[]
x = case SOP I '[]
x of {}
instance AsConstructor '[a] (Respond code description a) where
toConstructor :: ResponseType (Respond code description a) -> NP I '[a]
toConstructor ResponseType (Respond code description a)
x = a -> I a
forall a. a -> I a
I a
ResponseType (Respond code description a)
x I a -> NP I '[] -> NP I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil
fromConstructor :: NP I '[a] -> ResponseType (Respond code description a)
fromConstructor = I a -> a
forall a. I a -> a
unI (I a -> a) -> (NP I '[a] -> I a) -> NP I '[a] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NP I '[a] -> I a
forall {k} (f :: k -> Type) (x :: k) (xs :: [k]).
NP f (x : xs) -> f x
hd
instance AsConstructor '[a] (RespondAs (responseContentTypes :: Type) code description a) where
toConstructor :: ResponseType (RespondAs responseContentTypes code description a)
-> NP I '[a]
toConstructor ResponseType (RespondAs responseContentTypes code description a)
x = a -> I a
forall a. a -> I a
I a
ResponseType (RespondAs responseContentTypes code description a)
x I a -> NP I '[] -> NP I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil
fromConstructor :: NP I '[a]
-> ResponseType (RespondAs responseContentTypes code description a)
fromConstructor = I a -> a
forall a. I a -> a
unI (I a -> a) -> (NP I '[a] -> I a) -> NP I '[a] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NP I '[a] -> I a
forall {k} (f :: k -> Type) (x :: k) (xs :: [k]).
NP f (x : xs) -> f x
hd
instance AsConstructor '[] (RespondEmpty code description) where
toConstructor :: ResponseType (RespondEmpty code description) -> NP I '[]
toConstructor ResponseType (RespondEmpty code description)
_ = NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil
fromConstructor :: NP I '[] -> ResponseType (RespondEmpty code description)
fromConstructor NP I '[]
_ = ()
instance AsConstructor '[a] (WithHeaders headers a response) where
toConstructor :: ResponseType (WithHeaders headers a response) -> NP I '[a]
toConstructor ResponseType (WithHeaders headers a response)
a = a -> I a
forall a. a -> I a
I a
ResponseType (WithHeaders headers a response)
a I a -> NP I '[] -> NP I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP I '[]
forall {k} (a :: k -> Type). NP a '[]
Nil
fromConstructor :: NP I '[a] -> ResponseType (WithHeaders headers a response)
fromConstructor (I x
a :* NP I xs
Nil) = x
ResponseType (WithHeaders headers a response)
a
newtype GenericAsConstructor r = GenericAsConstructor r
type instance ResponseType (GenericAsConstructor r) = ResponseType r
instance
(GSOP.Code (ResponseType r) ~ '[xs], GSOP.Generic (ResponseType r)) =>
AsConstructor xs (GenericAsConstructor r)
where
toConstructor :: ResponseType (GenericAsConstructor r) -> NP I xs
toConstructor = NS (NP I) '[xs] -> NP I xs
forall {k} (f :: k -> Type) (x :: k). NS f '[x] -> f x
unZ (NS (NP I) '[xs] -> NP I xs)
-> (ResponseType r -> NS (NP I) '[xs]) -> ResponseType r -> NP I xs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOP I '[xs] -> NS (NP I) '[xs]
forall {k} (f :: k -> Type) (xss :: [[k]]).
SOP f xss -> NS (NP f) xss
unSOP (SOP I '[xs] -> NS (NP I) '[xs])
-> (ResponseType r -> SOP I '[xs])
-> ResponseType r
-> NS (NP I) '[xs]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResponseType r -> SOP I '[xs]
ResponseType r -> Rep (ResponseType r)
forall a. Generic a => a -> Rep a
GSOP.from
fromConstructor :: NP I xs -> ResponseType (GenericAsConstructor r)
fromConstructor = SOP I '[xs] -> ResponseType r
Rep (ResponseType r) -> ResponseType r
forall a. Generic a => Rep a -> a
GSOP.to (SOP I '[xs] -> ResponseType r)
-> (NP I xs -> SOP I '[xs]) -> NP I xs -> ResponseType r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NS (NP I) '[xs] -> SOP I '[xs]
forall k (f :: k -> Type) (xss :: [[k]]).
NS (NP f) xss -> SOP f xss
SOP (NS (NP I) '[xs] -> SOP I '[xs])
-> (NP I xs -> NS (NP I) '[xs]) -> NP I xs -> SOP I '[xs]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NP I xs -> NS (NP I) '[xs]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z
instance
(AsConstructor xs r, AsConstructors xss rs) =>
AsConstructors (xs ': xss) (r ': rs)
where
toSOP :: Union (ResponseTypes (r : rs)) -> SOP I (xs : xss)
toSOP (Z (I x
x)) = NS (NP I) (xs : xss) -> SOP I (xs : xss)
forall k (f :: k -> Type) (xss :: [[k]]).
NS (NP f) xss -> SOP f xss
SOP (NS (NP I) (xs : xss) -> SOP I (xs : xss))
-> (NP I xs -> NS (NP I) (xs : xss)) -> NP I xs -> SOP I (xs : xss)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NP I xs -> NS (NP I) (xs : xss)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (NP I xs -> SOP I (xs : xss)) -> NP I xs -> SOP I (xs : xss)
forall a b. (a -> b) -> a -> b
$ forall (xs :: [Type]) r.
AsConstructor xs r =>
ResponseType r -> NP I xs
toConstructor @xs @r x
ResponseType r
x
toSOP (S NS I xs
x) = NS (NP I) (xs : xss) -> SOP I (xs : xss)
forall k (f :: k -> Type) (xss :: [[k]]).
NS (NP f) xss -> SOP f xss
SOP (NS (NP I) (xs : xss) -> SOP I (xs : xss))
-> (SOP I xss -> NS (NP I) (xs : xss))
-> SOP I xss
-> SOP I (xs : xss)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NS (NP I) xss -> NS (NP I) (xs : xss)
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (NS (NP I) xss -> NS (NP I) (xs : xss))
-> (SOP I xss -> NS (NP I) xss)
-> SOP I xss
-> NS (NP I) (xs : xss)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOP I xss -> NS (NP I) xss
forall {k} (f :: k -> Type) (xss :: [[k]]).
SOP f xss -> NS (NP f) xss
unSOP (SOP I xss -> SOP I (xs : xss)) -> SOP I xss -> SOP I (xs : xss)
forall a b. (a -> b) -> a -> b
$ forall (xss :: [[Type]]) (rs :: [Type]).
AsConstructors xss rs =>
Union (ResponseTypes rs) -> SOP I xss
toSOP @xss @rs NS I xs
Union (ResponseTypes rs)
x
fromSOP :: SOP I (xs : xss) -> Union (ResponseTypes (r : rs))
fromSOP (SOP (Z NP I x
x)) = I (ResponseType r) -> NS I (ResponseType r : ResponseTypes rs)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (ResponseType r -> I (ResponseType r)
forall a. a -> I a
I (forall (xs :: [Type]) r.
AsConstructor xs r =>
NP I xs -> ResponseType r
fromConstructor @xs @r NP I xs
NP I x
x))
fromSOP (SOP (S NS (NP I) xs
x)) = Union (ResponseTypes rs)
-> NS I (ResponseType r : ResponseTypes rs)
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (forall (xss :: [[Type]]) (rs :: [Type]).
AsConstructors xss rs =>
SOP I xss -> Union (ResponseTypes rs)
fromSOP @xss @rs (NS (NP I) xss -> SOP I xss
forall k (f :: k -> Type) (xss :: [[k]]).
NS (NP f) xss -> SOP f xss
SOP NS (NP I) xss
NS (NP I) xs
x))
newtype GenericAsUnion rs a = GenericAsUnion a
instance
(GSOP.Code a ~ xss, GSOP.Generic a, AsConstructors xss rs) =>
AsUnion rs (GenericAsUnion rs a)
where
toUnion :: GenericAsUnion rs a -> Union (ResponseTypes rs)
toUnion (GenericAsUnion a
x) = forall (xss :: [[Type]]) (rs :: [Type]).
AsConstructors xss rs =>
SOP I xss -> Union (ResponseTypes rs)
fromSOP @xss @rs (a -> Rep a
forall a. Generic a => a -> Rep a
GSOP.from a
x)
fromUnion :: Union (ResponseTypes rs) -> GenericAsUnion rs a
fromUnion = a -> GenericAsUnion rs a
forall {k} (rs :: k) a. a -> GenericAsUnion rs a
GenericAsUnion (a -> GenericAsUnion rs a)
-> (Union (ResponseTypes rs) -> a)
-> Union (ResponseTypes rs)
-> GenericAsUnion rs a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOP I xss -> a
Rep a -> a
forall a. Generic a => Rep a -> a
GSOP.to (SOP I xss -> a)
-> (Union (ResponseTypes rs) -> SOP I xss)
-> Union (ResponseTypes rs)
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (xss :: [[Type]]) (rs :: [Type]).
AsConstructors xss rs =>
Union (ResponseTypes rs) -> SOP I xss
toSOP @xss @rs
instance
AsUnion
'[ RespondEmpty s1 desc1,
RespondEmpty s2 desc2
]
Bool
where
toUnion :: Bool
-> Union
(ResponseTypes '[RespondEmpty s1 desc1, RespondEmpty s2 desc2])
toUnion Bool
False = I () -> NS I '[(), ()]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (() -> I ()
forall a. a -> I a
I ())
toUnion Bool
True = Union '[()] -> NS I '[(), ()]
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (I () -> Union '[()]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (() -> I ()
forall a. a -> I a
I ()))
fromUnion :: Union
(ResponseTypes '[RespondEmpty s1 desc1, RespondEmpty s2 desc2])
-> Bool
fromUnion (Z (I ())) = Bool
False
fromUnion (S (Z (I ()))) = Bool
True
fromUnion (S (S NS I xs
x)) = case NS I xs
x of {}
instance
{-# OVERLAPPABLE #-}
(ResponseType r1 ~ (), ResponseType r2 ~ a) =>
AsUnion '[r1, r2] (Maybe a)
where
toUnion :: Maybe a -> Union (ResponseTypes '[r1, r2])
toUnion Maybe a
Nothing = I () -> NS I '[(), a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (() -> I ()
forall a. a -> I a
I ())
toUnion (Just a
x) = NS I '[a] -> NS I '[(), a]
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S (I a -> NS I '[a]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
Z (a -> I a
forall a. a -> I a
I a
x))
fromUnion :: Union (ResponseTypes '[r1, r2]) -> Maybe a
fromUnion (Z (I ())) = Maybe a
forall a. Maybe a
Nothing
fromUnion (S (Z (I x
x))) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
x
fromUnion (S (S NS I xs
x)) = case NS I xs
x of {}