on master help sign in
Update comment in Servant.Client.Generic
0132475Catherine Galkina
servant-client/servant-client.cabal+1−1
@@ -43,7 +43,7 @@ library
43 , base64-bytestring >= 1.0.0.1 && < 1.1
43 , base64-bytestring >= 1.0.0.1 && < 1.1
44 , bytestring >= 0.10 && < 0.11
44 , bytestring >= 0.10 && < 0.11
45 , exceptions >= 0.8 && < 0.9
45 , exceptions >= 0.8 && < 0.9
46− , generics-sop
46+ , generics-sop >= 0.1.0.0 && < 0.3
47 , http-api-data >= 0.3 && < 0.4
47 , http-api-data >= 0.3 && < 0.4
48 , http-client >= 0.4.18.1 && < 0.6
48 , http-client >= 0.4.18.1 && < 0.6
49 , http-client-tls >= 0.2.2 && < 0.4
49 , http-client-tls >= 0.2.2 && < 0.4
servant-client/src/Servant/Client/Generic.hs+51−4
@@ -12,7 +12,7 @@ module Servant.Client.Generic
12 , genericMkClientP
12 , genericMkClientP
13 ) where
13 ) where
14
14
15−import Generics.SOP (Code, Generic, I(..), NP(..), NS(Z), Rep, SOP(..), to)
15+import Generics.SOP (Code, Generic, I(..), NP(..), NS(Z), SOP(..), to)
16import Servant.API ((:<|>)(..))
16import Servant.API ((:<|>)(..))
17import Servant.Client (ClientM)
17import Servant.Client (ClientM)
18
18
@@ -38,7 +38,7 @@ import Servant.Client (ClientM)
38-- > , mkNestedClient :: Int -> NestedClient
38-- > , mkNestedClient :: Int -> NestedClient
39-- > } deriving GHC.Generic
39-- > } deriving GHC.Generic
40-- >
40-- >
41−-- > instance Generic.SOP.Generic APIClient
41+-- > instance Generics.SOP.Generic APIClient
42-- > instance (Client API ~ client) => ClientLike client APIClient
42-- > instance (Client API ~ client) => ClientLike client APIClient
43-- >
43-- >
44-- > data NestedClient = NestedClient
44-- > data NestedClient = NestedClient
@@ -46,11 +46,57 @@ import Servant.Client (ClientM)
46-- > , postBaz :: Maybe Char -> ClientM ()
46-- > , postBaz :: Maybe Char -> ClientM ()
47-- > } deriving GHC.Generic
47-- > } deriving GHC.Generic
48-- >
48-- >
49−-- > instance Generic.SOP.Generic NestedClient
49+-- > instance Generics.SOP.Generic NestedClient
50-- > instance (Client NestedAPI ~ client) => ClientLike client NestedClient
50-- > instance (Client NestedAPI ~ client) => ClientLike client NestedClient
51-- >
51-- >
52-- > mkAPIClient :: APIClient
52-- > mkAPIClient :: APIClient
53-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
53-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
54+--
55+-- By default, left-nested alternatives are expanded:
56+--
57+-- > type API1
58+-- > = "foo" :> Capture "x" Int :> Get '[JSON] Int
59+-- > :<|> "bar" :> QueryParam "a" Char :> Post '[JSON] String
60+-- >
61+-- > type API2
62+-- > = "baz" :> QueryParam "c" Char :> Post '[JSON] ()
63+-- >
64+-- > type API = API1 :<|> API2
65+-- >
66+-- > data APIClient = APIClient
67+-- > { getFoo :: Int -> ClientM Int
68+-- > , postBar :: Maybe Char -> ClientM String
69+-- > , postBaz :: Maybe Char -> ClientM ()
70+-- > } deriving GHC.Generic
71+-- >
72+-- > instance Generics.SOP.Generic APIClient
73+-- > instance (Client API ~ client) => ClientLike client APIClient
74+-- >
75+-- > mkAPIClient :: APIClient
76+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
77+--
78+-- If you want to define client for @API1@ as a separate data structure,
79+-- you can use 'genericMkClientP':
80+--
81+-- > data APIClient1 = APIClient1
82+-- > { getFoo :: Int -> ClientM Int
83+-- > , postBar :: Maybe Char -> ClientM String
84+-- > } deriving GHC.Generic
85+-- >
86+-- > instance Generics.SOP.Generic APIClient1
87+-- > instance (Client API1 ~ client) => ClientLike client APIClient1
88+-- >
89+-- > data APIClient = APIClient
90+-- > { mkAPIClient1 :: APIClient1
91+-- > , postBaz :: Maybe Char -> ClientM ()
92+-- > } deriving GHC.Generic
93+-- >
94+-- > instance Generics.SOP.Generic APIClient
95+-- > instance (Client API ~ client) => ClientLike client APIClient where
96+-- > mkClient = genericMkClientP
97+-- >
98+-- > mkAPIClient :: APIClient
99+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
54class ClientLike client custom where
100class ClientLike client custom where
55 mkClient :: client -> custom
101 mkClient :: client -> custom
56 default mkClient :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
102 default mkClient :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
@@ -100,11 +146,12 @@ instance {-# OVERLAPPABLE #-} (ClientList client acc ~ (client ': acc))
100 => GClientList client acc where
146 => GClientList client acc where
101 gClientList c acc = I c :* acc
147 gClientList c acc = I c :* acc
102
148
103−-- | Generate client structure from client type.
149+-- | Generate client structure from client type, expanding left-nested API (done by default).
104genericMkClientL :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
150genericMkClientL :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
105 => client -> custom
151 => client -> custom
106genericMkClientL = to . SOP . Z . gMkClientL . flip gClientList Nil
152genericMkClientL = to . SOP . Z . gMkClientL . flip gClientList Nil
107
153
154+-- | Generate client structure from client type, regarding left-nested API clients as separate data structures.
108genericMkClientP :: (Generic custom, Code custom ~ '[xs], GClientLikeP client xs)
155genericMkClientP :: (Generic custom, Code custom ~ '[xs], GClientLikeP client xs)
109 => client -> custom
156 => client -> custom
110genericMkClientP = to . SOP . Z . gMkClientP
157genericMkClientP = to . SOP . Z . gMkClientP