{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Mergeable.IsMap ( IsMap (..), selectBy, selectOr, FromList (..), ) where import Control.Monad.Except (MonadError (throwError)) #if MIN_VERSION_aeson(2,0,0) import Data.Aeson.Key (Key) import qualified Data.Aeson.KeyMap as A #endif import qualified Data.HashMap.Lazy as HM import Data.Mergeable.Internal.Merge (mergeNoDuplicates) import Data.Mergeable.Internal.NameCollision (NameCollision) import Relude class IsMap k m | m -> k where unsafeFromList :: [(k, a)] -> m a singleton :: k -> a -> m a lookup :: k -> m a -> Maybe a member :: k -> m a -> Bool member = selectOr False (const True) toAssoc :: m a -> [(k, a)] instance (Eq k, Hashable k) => IsMap k (HashMap k) where unsafeFromList = HM.fromList singleton = HM.singleton lookup = HM.lookup member = HM.member toAssoc = HM.toList #if MIN_VERSION_aeson(2,0,0) instance IsMap Key A.KeyMap where unsafeFromList = A.fromList singleton = A.singleton lookup = A.lookup member = A.member toAssoc = A.toList #endif selectBy :: (MonadError e m, IsMap k c, Monad m) => e -> k -> c a -> m a selectBy err = selectOr (throwError err) pure selectOr :: IsMap k c => d -> (a -> d) -> k -> c a -> d selectOr fb f key lib = maybe fb f (lookup key lib) class FromList m map k a where fromList :: (Monad m) => [(k, a)] -> m (map k a) instance (Hashable k, Eq k, MonadError e m, NameCollision e a) => FromList m HashMap k a where fromList = mergeNoDuplicates HM.fromList