prosidy-1.5.0.1: src/Prosidy/Types/Assoc.hs
{-|
Module : Prosidy.Types.Assoc
Description : An associative mapping of keys to values.
Copyright : ©2020 James Alexander Feldman-Crough
License : MPL-2.0
Maintainer : alex@fldcr.com
-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Prosidy.Types.Assoc (Assoc(..), asHashMap, fromHashMap, toHashMap) where
import Data.HashMap.Strict ( HashMap )
import GHC.Generics ( Generic )
import Data.Aeson ( ToJSON(..)
, FromJSON(..)
)
import Control.DeepSeq ( NFData )
import Data.Binary ( Binary(..) )
import Data.Hashable ( Hashable(..) )
import qualified Data.HashMap.Strict as HM
-- | An associative mapping of keys to values.
--
-- Currently implemented as a 'HashMap', this newtype wrapper allows us to:
--
-- 1) Add non-orphan instances to the underlying structure.
-- 2) Change the underlying type if needed.
newtype Assoc k v = Assoc (HashMap k v)
deriving stock (Generic)
deriving newtype (Eq, Foldable, Functor, Show, ToJSON, FromJSON, NFData, Semigroup, Monoid, Hashable)
instance (Eq k, Hashable k, Binary k, Binary v) => Binary (Assoc k v) where
get = Assoc . HM.fromList <$> get
put (Assoc hm) = put $ HM.toList hm
-- | Given a function which operates on a 'HashMap', return a function which
-- performs an equivalent transfromation on an 'Assoc'.
asHashMap
:: Functor f
=> (HashMap k v -> f (HashMap k' v'))
-> Assoc k v
-> f (Assoc k' v')
asHashMap f (Assoc a) = Assoc <$> f a
-- | Convert a 'HashMap' to an 'Assoc'.
fromHashMap :: HashMap k v -> Assoc k v
fromHashMap = Assoc
-- | Convert an 'Assoc' to a 'HashMap'.
toHashMap :: Assoc k v -> HashMap k v
toHashMap (Assoc hm) = hm