{-# 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)) 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) instance (Eq k, Hashable k) => IsMap k (HashMap k) where unsafeFromList = HM.fromList singleton = HM.singleton lookup = HM.lookup member = HM.member 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