-- |
-- A newtyped version of "Data.HashMap.Strict" with a 'Monoid' instance providing @'mappend' = 'M.unionWith' 'mappend'@.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Web.Route.Invertible.Map.MonoidHash
  ( MonoidHashMap(..)
  , insertMonoidHash
  , fromMonoidHashList
  , lookupMonoidHash
  ) where

import Prelude hiding (lookup)

import Data.Foldable (fold)
import Data.Hashable (Hashable)
import qualified Data.HashMap.Strict as M
import Data.Semigroup (Semigroup((<>)))

-- |A specialized version of 'M.HashMap'.
newtype MonoidHashMap k a = MonoidHashMap { MonoidHashMap k a -> HashMap k a
monoidHashMap :: M.HashMap k a }
  deriving (MonoidHashMap k a -> MonoidHashMap k a -> Bool
(MonoidHashMap k a -> MonoidHashMap k a -> Bool)
-> (MonoidHashMap k a -> MonoidHashMap k a -> Bool)
-> Eq (MonoidHashMap k a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k a.
(Eq k, Eq a) =>
MonoidHashMap k a -> MonoidHashMap k a -> Bool
/= :: MonoidHashMap k a -> MonoidHashMap k a -> Bool
$c/= :: forall k a.
(Eq k, Eq a) =>
MonoidHashMap k a -> MonoidHashMap k a -> Bool
== :: MonoidHashMap k a -> MonoidHashMap k a -> Bool
$c== :: forall k a.
(Eq k, Eq a) =>
MonoidHashMap k a -> MonoidHashMap k a -> Bool
Eq, a -> MonoidHashMap k a -> Bool
MonoidHashMap k m -> m
MonoidHashMap k a -> [a]
MonoidHashMap k a -> Bool
MonoidHashMap k a -> Int
MonoidHashMap k a -> a
MonoidHashMap k a -> a
MonoidHashMap k a -> a
MonoidHashMap k a -> a
(a -> m) -> MonoidHashMap k a -> m
(a -> m) -> MonoidHashMap k a -> m
(a -> b -> b) -> b -> MonoidHashMap k a -> b
(a -> b -> b) -> b -> MonoidHashMap k a -> b
(b -> a -> b) -> b -> MonoidHashMap k a -> b
(b -> a -> b) -> b -> MonoidHashMap k a -> b
(a -> a -> a) -> MonoidHashMap k a -> a
(a -> a -> a) -> MonoidHashMap k a -> a
(forall m. Monoid m => MonoidHashMap k m -> m)
-> (forall m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m)
-> (forall m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m)
-> (forall a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b)
-> (forall a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b)
-> (forall b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b)
-> (forall b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b)
-> (forall a. (a -> a -> a) -> MonoidHashMap k a -> a)
-> (forall a. (a -> a -> a) -> MonoidHashMap k a -> a)
-> (forall a. MonoidHashMap k a -> [a])
-> (forall a. MonoidHashMap k a -> Bool)
-> (forall a. MonoidHashMap k a -> Int)
-> (forall a. Eq a => a -> MonoidHashMap k a -> Bool)
-> (forall a. Ord a => MonoidHashMap k a -> a)
-> (forall a. Ord a => MonoidHashMap k a -> a)
-> (forall a. Num a => MonoidHashMap k a -> a)
-> (forall a. Num a => MonoidHashMap k a -> a)
-> Foldable (MonoidHashMap k)
forall a. Eq a => a -> MonoidHashMap k a -> Bool
forall a. Num a => MonoidHashMap k a -> a
forall a. Ord a => MonoidHashMap k a -> a
forall m. Monoid m => MonoidHashMap k m -> m
forall a. MonoidHashMap k a -> Bool
forall a. MonoidHashMap k a -> Int
forall a. MonoidHashMap k a -> [a]
forall a. (a -> a -> a) -> MonoidHashMap k a -> a
forall k a. Eq a => a -> MonoidHashMap k a -> Bool
forall k a. Num a => MonoidHashMap k a -> a
forall k a. Ord a => MonoidHashMap k a -> a
forall m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m
forall k m. Monoid m => MonoidHashMap k m -> m
forall k a. MonoidHashMap k a -> Bool
forall k a. MonoidHashMap k a -> Int
forall k a. MonoidHashMap k a -> [a]
forall b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b
forall a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b
forall k a. (a -> a -> a) -> MonoidHashMap k a -> a
forall k m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m
forall k b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b
forall k a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: MonoidHashMap k a -> a
$cproduct :: forall k a. Num a => MonoidHashMap k a -> a
sum :: MonoidHashMap k a -> a
$csum :: forall k a. Num a => MonoidHashMap k a -> a
minimum :: MonoidHashMap k a -> a
$cminimum :: forall k a. Ord a => MonoidHashMap k a -> a
maximum :: MonoidHashMap k a -> a
$cmaximum :: forall k a. Ord a => MonoidHashMap k a -> a
elem :: a -> MonoidHashMap k a -> Bool
$celem :: forall k a. Eq a => a -> MonoidHashMap k a -> Bool
length :: MonoidHashMap k a -> Int
$clength :: forall k a. MonoidHashMap k a -> Int
null :: MonoidHashMap k a -> Bool
$cnull :: forall k a. MonoidHashMap k a -> Bool
toList :: MonoidHashMap k a -> [a]
$ctoList :: forall k a. MonoidHashMap k a -> [a]
foldl1 :: (a -> a -> a) -> MonoidHashMap k a -> a
$cfoldl1 :: forall k a. (a -> a -> a) -> MonoidHashMap k a -> a
foldr1 :: (a -> a -> a) -> MonoidHashMap k a -> a
$cfoldr1 :: forall k a. (a -> a -> a) -> MonoidHashMap k a -> a
foldl' :: (b -> a -> b) -> b -> MonoidHashMap k a -> b
$cfoldl' :: forall k b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b
foldl :: (b -> a -> b) -> b -> MonoidHashMap k a -> b
$cfoldl :: forall k b a. (b -> a -> b) -> b -> MonoidHashMap k a -> b
foldr' :: (a -> b -> b) -> b -> MonoidHashMap k a -> b
$cfoldr' :: forall k a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b
foldr :: (a -> b -> b) -> b -> MonoidHashMap k a -> b
$cfoldr :: forall k a b. (a -> b -> b) -> b -> MonoidHashMap k a -> b
foldMap' :: (a -> m) -> MonoidHashMap k a -> m
$cfoldMap' :: forall k m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m
foldMap :: (a -> m) -> MonoidHashMap k a -> m
$cfoldMap :: forall k m a. Monoid m => (a -> m) -> MonoidHashMap k a -> m
fold :: MonoidHashMap k m -> m
$cfold :: forall k m. Monoid m => MonoidHashMap k m -> m
Foldable, Int -> MonoidHashMap k a -> ShowS
[MonoidHashMap k a] -> ShowS
MonoidHashMap k a -> String
(Int -> MonoidHashMap k a -> ShowS)
-> (MonoidHashMap k a -> String)
-> ([MonoidHashMap k a] -> ShowS)
-> Show (MonoidHashMap k a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k a. (Show k, Show a) => Int -> MonoidHashMap k a -> ShowS
forall k a. (Show k, Show a) => [MonoidHashMap k a] -> ShowS
forall k a. (Show k, Show a) => MonoidHashMap k a -> String
showList :: [MonoidHashMap k a] -> ShowS
$cshowList :: forall k a. (Show k, Show a) => [MonoidHashMap k a] -> ShowS
show :: MonoidHashMap k a -> String
$cshow :: forall k a. (Show k, Show a) => MonoidHashMap k a -> String
showsPrec :: Int -> MonoidHashMap k a -> ShowS
$cshowsPrec :: forall k a. (Show k, Show a) => Int -> MonoidHashMap k a -> ShowS
Show)

instance (Eq k, Hashable k, Semigroup a) => Semigroup (MonoidHashMap k a) where
  MonoidHashMap HashMap k a
a <> :: MonoidHashMap k a -> MonoidHashMap k a -> MonoidHashMap k a
<> MonoidHashMap HashMap k a
b = HashMap k a -> MonoidHashMap k a
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap (HashMap k a -> MonoidHashMap k a)
-> HashMap k a -> MonoidHashMap k a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> HashMap k a -> HashMap k a -> HashMap k a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v
M.unionWith a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>) HashMap k a
a HashMap k a
b

-- |'mappend' is equivalent to @'M.unionWith' 'mappend'@.
instance (Eq k, Hashable k, Monoid a) => Monoid (MonoidHashMap k a) where
  mempty :: MonoidHashMap k a
mempty = HashMap k a -> MonoidHashMap k a
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap HashMap k a
forall k v. HashMap k v
M.empty
  mappend :: MonoidHashMap k a -> MonoidHashMap k a -> MonoidHashMap k a
mappend (MonoidHashMap HashMap k a
a) (MonoidHashMap HashMap k a
b) = HashMap k a -> MonoidHashMap k a
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap (HashMap k a -> MonoidHashMap k a)
-> HashMap k a -> MonoidHashMap k a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> HashMap k a -> HashMap k a -> HashMap k a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v
M.unionWith a -> a -> a
forall a. Monoid a => a -> a -> a
mappend HashMap k a
a HashMap k a
b

instance Functor (MonoidHashMap k) where
  fmap :: (a -> b) -> MonoidHashMap k a -> MonoidHashMap k b
fmap a -> b
f (MonoidHashMap HashMap k a
m) = HashMap k b -> MonoidHashMap k b
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap (HashMap k b -> MonoidHashMap k b)
-> HashMap k b -> MonoidHashMap k b
forall a b. (a -> b) -> a -> b
$ (a -> b) -> HashMap k a -> HashMap k b
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
M.map a -> b
f HashMap k a
m

-- |Insert a new key and value in the map. If the key is already present in the map, the associated value is combined with the supplied value. Equivalent to @'M.insertWith' 'mappend'@.
insertMonoidHash :: (Eq k, Hashable k, Monoid a) => k -> a -> MonoidHashMap k a -> MonoidHashMap k a
insertMonoidHash :: k -> a -> MonoidHashMap k a -> MonoidHashMap k a
insertMonoidHash k
k a
a (MonoidHashMap HashMap k a
m) = HashMap k a -> MonoidHashMap k a
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap (HashMap k a -> MonoidHashMap k a)
-> HashMap k a -> MonoidHashMap k a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> k -> a -> HashMap k a -> HashMap k a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
M.insertWith a -> a -> a
forall a. Monoid a => a -> a -> a
mappend k
k a
a HashMap k a
m

-- |Build a map from a list of key/value pairs. If the list contains more than one value for the same key, the values are combined. Equivalent to @'M.fromListWith' 'mappend'@.
fromMonoidHashList :: (Eq k, Hashable k, Monoid a) => [(k, a)] -> MonoidHashMap k a
fromMonoidHashList :: [(k, a)] -> MonoidHashMap k a
fromMonoidHashList = HashMap k a -> MonoidHashMap k a
forall k a. HashMap k a -> MonoidHashMap k a
MonoidHashMap (HashMap k a -> MonoidHashMap k a)
-> ([(k, a)] -> HashMap k a) -> [(k, a)] -> MonoidHashMap k a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> a) -> [(k, a)] -> HashMap k a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
M.fromListWith a -> a -> a
forall a. Monoid a => a -> a -> a
mappend

-- |Lookup the value at a key in the map, returning 'mempty' if the key isn't in the map.
lookupMonoidHash :: (Eq k, Hashable k, Monoid a) => k -> MonoidHashMap k a -> a
lookupMonoidHash :: k -> MonoidHashMap k a -> a
lookupMonoidHash k
k (MonoidHashMap HashMap k a
m) = Maybe a -> a
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (Maybe a -> a) -> Maybe a -> a
forall a b. (a -> b) -> a -> b
$ k -> HashMap k a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
M.lookup k
k HashMap k a
m