Skip to content

Commit d81c8d9

Browse files
author
Gaël Deest
committed
Add parameter-supplying operator
Renamed `(/:)` to `(//)`, and used `(/:)` for supplying parameters to client functions. Should close #1442.
1 parent 6718752 commit d81c8d9

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

servant-client-core/src/Servant/Client/Core/HasClient.hs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module Servant.Client.Core.HasClient (
2727
HasClient (..),
2828
EmptyClient (..),
2929
AsClientT,
30+
(//),
3031
(/:),
3132
foldMapUnion,
3233
matchUnion,
@@ -54,7 +55,8 @@ import Data.Sequence
5455
(fromList)
5556
import qualified Data.Text as T
5657
import Network.HTTP.Media
57-
(MediaType, matches, parseAccept, (//))
58+
(MediaType, matches, parseAccept)
59+
import qualified Network.HTTP.Media as Media
5860
import qualified Data.Sequence as Seq
5961
import Data.SOP.BasicFunctors
6062
(I (I), (:.:) (Comp))
@@ -873,9 +875,12 @@ instance
873875

874876
#endif
875877

876-
infixl 1 /:
878+
infixl 1 //
879+
infixl 2 /:
877880

878-
-- | Convenience function for working with nested record-clients.
881+
-- | Helper to make code using records of clients more readable.
882+
--
883+
-- Can be mixed with (/:) for supplying arguments.
879884
--
880885
-- Example:
881886
--
@@ -899,10 +904,46 @@ infixl 1 /:
899904
-- rootClient = client api
900905
--
901906
-- endpointClient :: ClientM Person
902-
-- endpointClient = client /: subApi /: endpoint
907+
-- endpointClient = client // subApi // endpoint
908+
-- @@
909+
(//) :: a -> (a -> b) -> b
910+
x // f = f x
911+
912+
-- | Convenience function for supplying arguments to client functions when
913+
-- working with records of clients.
914+
--
915+
-- Intended to be use in conjunction with '(//)'.
916+
--
917+
-- Example:
918+
--
919+
-- @@
920+
-- type Api = NamedAPI RootApi
921+
--
922+
-- data RootApi mode = RootApi
923+
-- { subApi :: mode :- Capture "token" String :> NamedAPI SubApi
924+
-- , hello :: mode :- Capture "name" String :> Get '[JSON] String
925+
-- , …
926+
-- } deriving Generic
927+
--
928+
-- data SubAmi mode = SubApi
929+
-- { endpoint :: mode :- Get '[JSON] Person
930+
-- , …
931+
-- } deriving Generic
932+
--
933+
-- api :: Proxy API
934+
-- api = Proxy
935+
--
936+
-- rootClient :: RootApi (AsClientT ClientM)
937+
-- rootClient = client api
938+
--
939+
-- hello :: String -> ClientM String
940+
-- hello name = rootClient // hello /: name
941+
--
942+
-- endpointClient :: ClientM Person
943+
-- endpointClient = client // subApi /: "foobar123" // endpoint
903944
-- @@
904-
(/:) :: a -> (a -> b) -> b
905-
x /: f = f x
945+
(/:) :: (a -> b -> c) -> b -> a -> c
946+
(/:) = flip
906947

907948

908949
{- Note [Non-Empty Content Types]
@@ -928,7 +969,7 @@ for empty and one for non-empty lists).
928969
checkContentTypeHeader :: RunClient m => Response -> m MediaType
929970
checkContentTypeHeader response =
930971
case lookup "Content-Type" $ toList $ responseHeaders response of
931-
Nothing -> return $ "application"//"octet-stream"
972+
Nothing -> return $ "application" Media.// "octet-stream"
932973
Just t -> case parseAccept t of
933974
Nothing -> throwClientError $ InvalidContentTypeHeader response
934975
Just t' -> return t'

servant-client-core/src/Servant/Client/Core/Reexport.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Servant.Client.Core.Reexport
88
, foldMapUnion
99
, matchUnion
1010
, AsClientT
11+
, (//)
1112
, (/:)
1213

1314
-- * Response (for @Raw@)

servant-client/test/Servant/ClientTestUtils.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ type TestHeaders = '[Header "X-Example1" Int, Header "X-Example2" String]
111111
data RecordRoutes mode = RecordRoutes
112112
{ version :: mode :- "version" :> Get '[JSON] Int
113113
, echo :: mode :- "echo" :> Capture "string" String :> Get '[JSON] String
114-
, otherRoutes :: mode :- "other" :> NamedRoutes OtherRoutes
114+
, otherRoutes :: mode :- "other" :> Capture "someParam" Int :> NamedRoutes OtherRoutes
115115
} deriving Generic
116116

117117
data OtherRoutes mode = OtherRoutes
@@ -246,7 +246,7 @@ server = serve api (
246246
:<|> RecordRoutes
247247
{ version = pure 42
248248
, echo = pure
249-
, otherRoutes = OtherRoutes
249+
, otherRoutes = \_ -> OtherRoutes
250250
{ something = pure ["foo", "bar", "pweet"]
251251
}
252252
}

servant-client/test/Servant/GenericSpec.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module Servant.GenericSpec (spec) where
1919

2020
import Test.Hspec
2121

22-
import Servant.Client ((/:))
22+
import Servant.Client ((//), (/:))
2323
import Servant.ClientTestUtils
2424

2525
spec :: Spec
@@ -31,7 +31,7 @@ genericSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
3131
context "Record clients work as expected" $ do
3232

3333
it "Client functions return expected values" $ \(_,baseUrl) -> do
34-
runClient (recordRoutes /: version) baseUrl `shouldReturn` Right 42
35-
runClient (recordRoutes /: echo $ "foo") baseUrl `shouldReturn` Right "foo"
34+
runClient (recordRoutes // version) baseUrl `shouldReturn` Right 42
35+
runClient (recordRoutes // echo /: "foo") baseUrl `shouldReturn` Right "foo"
3636
it "Clients can be nested" $ \(_,baseUrl) -> do
37-
runClient (recordRoutes /: otherRoutes /: something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]
37+
runClient (recordRoutes // otherRoutes /: 42 // something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]

0 commit comments

Comments
 (0)