-
Notifications
You must be signed in to change notification settings - Fork 1
/
Heather.hs
77 lines (66 loc) · 2.64 KB
/
Heather.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{-# LANGUAGE OverloadedStrings #-}
module Heather where
import Data.Aeson
import Data.Text
import Control.Applicative
import Control.Monad
import Network.HTTP.Conduit (simpleHttp)
import Data.Time.Clock (UTCTime)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
-- put your API key here
apikey :: String
apikey = "API KEY GOES HERE"
-- the OpenWeatherMap API url
url :: (Show a) => String -> String -> a -> String
url q appid z = "http://api.openweathermap.org/data/2.5/" ++ q ++ "?q=" ++ (show z) ++ "&units=imperial&appid=" ++ appid
-- city datatype
data City = City { name :: String
, country :: String } deriving Show
-- cities contain "name" and "country" fields in the JSON schema
instance FromJSON City where
parseJSON (Object o) = City <$>
o .: "name" <*>
o .: "country"
parseJSON _ = mzero
-- weather datatype
data Weather =
Weather { temperature :: Float -- degrees Farenheit
, pressure :: Float -- hPa
, humidity :: Float -- %
, windspeed :: Float -- miles/hour
, clouds :: Float -- %
, category :: Text -- short description
, description :: Text -- long description
, time :: UTCTime -- POSIX timestamp
, icon :: Text } deriving (Show)
-- parse the weather JSON schema
instance FromJSON Weather where
parseJSON (Object o) = Weather <$>
(main >>= (.: "temp")) <*>
(main >>= (.: "pressure")) <*>
(main >>= (.: "humidity")) <*>
(wind >>= (.: "speed")) <*>
(cloud >>= (.: "all")) <*>
(desc >>= (.: "main")) <*>
(desc >>= (.: "description")) <*>
liftM parseTime (o .: "dt") <*>
(desc >>= (.: "icon"))
where main = (o .: "main")
wind = (o .: "wind")
cloud = (o .: "clouds")
desc = (!! 0) <$> (o .: "weather")
parseTime = posixSecondsToUTCTime . fromIntegral :: Int -> UTCTime
-- a Forecast is a container for city + a list of weather data
data Forecast = Forecast { city :: City, weather :: [Weather] } deriving Show
-- pare the full JSON response
instance FromJSON Forecast where
parseJSON (Object o) = do
c <- parseJSON =<< (o .: "city")
w <- parseJSON =<< (o .: "list")
return $ Forecast c w
parseJSON _ = mzero
-- main functions for querying the API and parsing the JSON response
getForecast :: (Show a) => a -> IO (Either String Forecast)
getForecast z = eitherDecode <$> ((simpleHttp . (url "forecast" apikey)) z)
getCurrent :: (Show a) => a -> IO (Either String Weather)
getCurrent z = eitherDecode <$> ((simpleHttp . (url "weather" apikey)) z)