prosidy-1.6.0.2: 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 Safe #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}
module Prosidy.Types.Assoc
( Assoc(..)
, asHashMap
, fromHashMap
, toHashMap
, toEntries
)
where
import Prosidy.Internal.Classes
import Data.HashMap.Strict ( HashMap )
import qualified Data.HashMap.Strict as HM
import qualified Data.Text.Prettyprint.Doc as PP
-- | 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 (Generic)
deriving (Eq, Show, ToJSON, FromJSON, NFData, Semigroup, Monoid, Hashable) via HashMap k v
deriving (Foldable, Functor) via HashMap k
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
instance (Pretty k, Pretty v) => Pretty (Assoc k v) where
pretty (Assoc hm) =
PP.list
. map (\(k, v) -> pretty k PP.<+> PP.equals PP.<+> pretty v)
$ 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
-- | Convert an 'Assoc' into a list of key/value pairs.
toEntries :: Assoc k v -> [(k, v)]
toEntries (Assoc hm) = HM.toList hm