From 27b29703a46bcde319961c2b52d38da3513a1da8 Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Sun, 28 Jun 2020 17:36:49 +0200 Subject: Make location a part of API --- lib/Web/OpenWeatherMap/API.hs | 44 ++++++-------------------------- lib/Web/OpenWeatherMap/Client.hs | 21 ++++----------- lib/Web/OpenWeatherMap/Types/Location.hs | 34 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 52 deletions(-) create mode 100644 lib/Web/OpenWeatherMap/Types/Location.hs (limited to 'lib') diff --git a/lib/Web/OpenWeatherMap/API.hs b/lib/Web/OpenWeatherMap/API.hs index 516845c..8dde5c7 100644 --- a/lib/Web/OpenWeatherMap/API.hs +++ b/lib/Web/OpenWeatherMap/API.hs @@ -6,10 +6,8 @@ For API key (a.k.a appid) refer to . {-# LANGUAGE TypeOperators #-} module Web.OpenWeatherMap.API - ( weatherByName - , weatherByCoord - , forecastByName - , forecastByCoord + ( currentWeather + , forecastWeather ) where import Data.Proxy (Proxy(..)) @@ -19,44 +17,18 @@ import Servant.Client (ClientM, client) import Web.OpenWeatherMap.Types.CurrentWeather (CurrentWeather) import Web.OpenWeatherMap.Types.ForecastWeather (ForecastWeather) +import Web.OpenWeatherMap.Types.Location (Location) type QueryParam = QueryParam' '[ Required, Strict] -type GetCurrentWeather = AppId :> Get '[ JSON] CurrentWeather - -type GetForecastWeather = AppId :> Get '[ JSON] ForecastWeather - -type AppId = QueryParam "appid" String - type Current - = "weather" :> (QueryParam "q" String :> GetCurrentWeather :<|> QueryParam "lat" Double :> QueryParam "lon" Double :> GetCurrentWeather) + = "weather" :> QueryParam "appid" String :> Location :> Get '[ JSON] CurrentWeather type Forecast - = "forecast" :> (QueryParam "q" String :> GetForecastWeather :<|> QueryParam "lat" Double :> QueryParam "lon" Double :> GetForecastWeather) + = "forecast" :> QueryParam "appid" String :> Location :> Get '[ JSON] ForecastWeather type API = Current :<|> Forecast --- | Request current weather in the city. -weatherByName :: - String -- ^ City name, e. g. \"Moscow\" or \"Moscow,ru\". - -> String -- ^ API key. - -> ClientM CurrentWeather --- | Request current weather at the geographic coordinates (in decimal degrees). -weatherByCoord :: - Double -- ^ Latitude, e. g. 55.7522200 for Moscow. - -> Double -- ^ Longitude, e. g. 37.6155600 for Moscow. - -> String -- ^ API key. - -> ClientM CurrentWeather --- | Request forecast weather in the city. -forecastByName :: - String -- ^ City name, e. g. \"Moscow\" or \"Moscow,ru\". - -> String -- ^ API key. - -> ClientM ForecastWeather --- | Request current weather at the geographic coordinates (in decimal degrees). -forecastByCoord :: - Double -- ^ Latitude, e. g. 55.7522200 for Moscow. - -> Double -- ^ Longitude, e. g. 37.6155600 for Moscow. - -> String -- ^ API key. - -> ClientM ForecastWeather -(weatherByName :<|> weatherByCoord) :<|> (forecastByName :<|> forecastByCoord) = - client (Proxy :: Proxy API) +forecastWeather :: String -> Location -> ClientM ForecastWeather +currentWeather :: String -> Location -> ClientM CurrentWeather +(currentWeather :<|> forecastWeather) = client (Proxy :: Proxy API) diff --git a/lib/Web/OpenWeatherMap/Client.hs b/lib/Web/OpenWeatherMap/Client.hs index d760812..31719bb 100644 --- a/lib/Web/OpenWeatherMap/Client.hs +++ b/lib/Web/OpenWeatherMap/Client.hs @@ -2,8 +2,7 @@ High-level client functions perfoming requests to OpenWeatherMap API. -} module Web.OpenWeatherMap.Client - ( Location(..) - , getWeather + ( getWeather , getForecast ) where @@ -20,12 +19,7 @@ import Servant.Client import qualified Web.OpenWeatherMap.API as API import Web.OpenWeatherMap.Types.CurrentWeather (CurrentWeather) import Web.OpenWeatherMap.Types.ForecastWeather (ForecastWeather) - --- | Various way to specify location. -data Location - = Name String -- ^ City name. - | Coord Double - Double -- ^ Geographic coordinates: latitude and longitude. +import Web.OpenWeatherMap.Types.Location (Location) -- | Make a request to OpenWeatherMap API -- and return current weather in given location. @@ -33,10 +27,7 @@ getWeather :: String -- ^ API key. -> Location -> IO (Either ClientError CurrentWeather) -getWeather appid loc = defaultEnv >>= runClientM (api loc appid) - where - api (Name city) = API.weatherByName city - api (Coord lat lon) = API.weatherByCoord lat lon +getWeather appid loc = defaultEnv >>= runClientM (API.currentWeather appid loc) -- | Make a request to OpenWeatherMap API -- and return forecast weather in given location. @@ -44,10 +35,8 @@ getForecast :: String -- ^ API key. -> Location -> IO (Either ClientError ForecastWeather) -getForecast appid loc = defaultEnv >>= runClientM (api loc appid) - where - api (Name city) = API.forecastByName city - api (Coord lat lon) = API.forecastByCoord lat lon +getForecast appid loc = + defaultEnv >>= runClientM (API.forecastWeather appid loc) defaultEnv :: IO ClientEnv defaultEnv = do diff --git a/lib/Web/OpenWeatherMap/Types/Location.hs b/lib/Web/OpenWeatherMap/Types/Location.hs new file mode 100644 index 0000000..72712ed --- /dev/null +++ b/lib/Web/OpenWeatherMap/Types/Location.hs @@ -0,0 +1,34 @@ +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} + +module Web.OpenWeatherMap.Types.Location + ( Location(..) + ) where + +import Data.Proxy (Proxy(..)) + +import Servant.API ((:>)) +import Servant.Client (Client, HasClient, clientWithRoute, hoistClientMonad) +import Servant.Client.Core.Request (appendToQueryString) +import Web.HttpApiData (toQueryParam) + +-- | Various way to specify location. +data Location + = Name String -- ^ City name. + | Coord Double Double -- ^ Geographic coordinates: latitude and longitude. + +instance HasClient m api => HasClient m (Location :> api) where + type Client m (Location :> api) = Location -> Client m api + clientWithRoute pm Proxy req loc = + clientWithRoute pm (Proxy :: Proxy api) (addParams loc req) + where + addParams (Name q) = appendToQueryString "q" (Just $ toQueryParam q) + addParams (Coord lat lon) = + appendToQueryString "lat" (Just $ toQueryParam lat) . + appendToQueryString "lon" (Just $ toQueryParam lon) + hoistClientMonad pm _ f cl = + \a -> hoistClientMonad pm (Proxy :: Proxy api) f (cl a) -- cgit v1.2.3