{-| Districts can be encoded to and decoded from JSON: >>> import Data.Aeson (decode, encode) >>> import Data.ByteString.Lazy.Char8 (pack) >>> encode Palolene "\"Palolene\"" >>> encode [ Lakos, SouthernPalolene ] "[\"Lakos\",\"SouthernPalolene\"]" >>> decode . pack $ "[ \"Lakos\" ]" :: Maybe [District] Just [Lakos] -} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} module Malodivo.Types.District ( District(..) , DistrictFunds , DistrictInfo(..) , di2df , df2di ) where import Control.Arrow ((&&&)) import GHC.Generics (Generic) import Data.Aeson (FromJSON, ToJSON) import qualified Data.HashMap.Strict as HM import Data.Hashable (Hashable) -- | District of the Kindom of Malodivo. data District = Palolene | SouthernPalolene | Lakos deriving (Eq, Hashable, Show, Generic, FromJSON, ToJSON) -- | Convenient type. type DistrictFunds = HM.HashMap District Integer {-| We use this data type instead of 'DistrictFunds' for JSON, because maps other than @HashMap Text _@ are hard to decode/encode see . Anyway, we still have type-checked typos-proof structure. -} data DistrictInfo = DistrictInfo { name :: District , amount :: Integer } deriving (Generic, FromJSON, ToJSON) di2df :: [DistrictInfo] -> DistrictFunds di2df = HM.fromListWith (+) . map (name &&& amount) df2di :: DistrictFunds -> [DistrictInfo] df2di = map (\(n, a) -> DistrictInfo {name = n, amount = a}) . HM.toList