[Haskell-cafe] Code review - wrapping servant client to hide required parameters
Nigel Rantor
wiggly at wiggly.org
Mon Jan 2 16:05:43 UTC 2017
Hello,
So, I am still learning and would like someone to cast an eye over some
code to see if I am missing something in terms of making it cleaner/more
concise.
I have begun wrapping the They Work For You API using the Servant Client
library.
All code is already online for you to grab at;
https://github.com/wiggly/twfy-api-client
https://hackage.haskell.org/package/twfy-api-client
The API is not under my control so I can't change how it works or how it
accepts parameters.
Every API call requires a Key to be passed as a query string parameter.
For a particular session/user this will always be the same, and there is
no point in allowing the user to not provide it.
Since it is a query parameter Servant forces the type to be within
Maybe. For example;
type TwfyAPI = "getConstituency" :> QueryParam "key" ApiKey :>
QueryParam "name" T.Text :> QueryParam "postcode" T.Text :> Get
'[JsonIso8859] Constituency
Gives the following function signature;
getConstituency :: Maybe ApiKey -- ^ API key
-> Maybe T.Text -- ^ Name
-> Maybe T.Text -- ^ Post code
-> ClientM Constituency
To make the API easier to use I have created a Client module that wraps
these so that I can hide the passing of the API key for every call, and
also allow the user to not have to deal with http client managers or URL
parsing if they don't want to. The upshot is that I get a signature that
now accepts a data type I have created that contains all the information
required to run the client action and return a result, like so (where
A.getConstituency is the function above taking a Maybe ApiKey as first
argument);
getConstituency :: Client
-> Maybe T.Text -- ^ Name
-> Maybe T.Text -- ^ Post code
-> IO (Either ServantError Constituency)
getConstituency c = do
let key = Just $ clientApiKey c
env = clientEnv c
in (\name postCode -> (flip runClientM) env (A.getConstituency
key name postCode))
So, this wraps up all of the calling of the servant client with an
appropriate environment and arguments.
I have two questions;
1) What do people think of this style of wrapping the servant client calls?
2) I am now returning a lambda that accepts the remaining arguments to
the call, is there any way I can make this cleaner? i.e. is it possible
for me to not have to specifically re-write all of the function
parameters using something like uncurry or other machinery? I have
played with trying to use uncurry but got nowhere fast.
Thanks in advance,
Nigel
More information about the Haskell-Cafe
mailing list