xml-parser-0.1: library/XmlParser/TupleHashMap.hs
module XmlParser.TupleHashMap
( TupleHashMap,
KeyConstraints,
empty,
insertSemigroup,
alterF,
toList,
)
where
import qualified Data.HashMap.Strict as HashMap
import XmlParser.Prelude hiding (empty, fromList, toList)
newtype TupleHashMap k1 k2 v = TupleHashMap (HashMap k1 (HashMap k2 v))
-- |
-- Serves to reduce noise in signatures.
type KeyConstraints k1 k2 = (Eq k1, Hashable k1, Eq k2, Hashable k2)
empty :: TupleHashMap k1 k2 v
empty =
TupleHashMap HashMap.empty
insertSemigroup :: (Semigroup v, KeyConstraints k1 k2) => k1 -> k2 -> v -> TupleHashMap k1 k2 v -> TupleHashMap k1 k2 v
insertSemigroup k1 k2 v (TupleHashMap map1) =
HashMap.alter
( maybe
(Just (HashMap.singleton k2 v))
(Just . HashMap.insertWith (<>) k2 v)
)
k1
map1
& TupleHashMap
alterF :: (Functor f, KeyConstraints k1 k2) => (Maybe v -> f (Maybe v)) -> k1 -> k2 -> TupleHashMap k1 k2 v -> f (TupleHashMap k1 k2 v)
alterF fn k1 k2 (TupleHashMap map1) =
HashMap.alterF
( \case
Just map2 ->
HashMap.alterF fn k2 map2
& fmap (\map2 -> if HashMap.null map2 then Nothing else Just map2)
Nothing ->
fn Nothing
& (fmap . fmap) (HashMap.singleton k2)
)
k1
map1
& fmap TupleHashMap
toList :: TupleHashMap k1 k2 b -> [(k1, k2, b)]
toList (TupleHashMap map1) =
do
(k1, map2) <- HashMap.toList map1
(k2, v) <- HashMap.toList map2
return (k1, k2, v)