{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Data.Morpheus.Ext.OrdMap
( OrdMap (..),
unsafeFromList,
)
where
import qualified Data.HashMap.Lazy as HM
import Data.Morpheus.Error.NameCollision (NameCollision (..))
import Data.Morpheus.Ext.Elems (Elems (..))
import Data.Morpheus.Ext.Map
( Indexed (..),
indexed,
)
import Data.Morpheus.Ext.SemigroupM
( SemigroupM (..),
)
import Data.Morpheus.Internal.Utils
( Collection (..),
Failure,
FromElems (..),
KeyOf (..),
Selectable (..),
toPair,
)
import Data.Morpheus.Types.Internal.AST.Base (ValidationErrors)
import Language.Haskell.TH.Syntax (Lift (..))
import Relude
-- OrdMap
newtype OrdMap k a = OrdMap
{ mapEntries :: HashMap k (Indexed k a)
}
deriving
( Show,
Eq,
Functor,
Traversable
)
instance (Lift a, Lift k, Eq k, Hashable k) => Lift (OrdMap k a) where
lift (OrdMap x) = [|OrdMap (HM.fromList ls)|]
where
ls = HM.toList x
#if MIN_VERSION_template_haskell(2,16,0)
liftTyped (OrdMap x) = [||OrdMap (HM.fromList ls)||]
where
ls = HM.toList x
#endif
instance (Eq k, Hashable k) => Foldable (OrdMap k) where
foldMap f = foldMap f . getElements
getElements :: (Eq k, Hashable k) => OrdMap k b -> [b]
getElements = fmap indexedValue . sortOn index . toList . mapEntries
instance (KeyOf k a, Hashable k) => Collection a (OrdMap k a) where
empty = OrdMap HM.empty
singleton x = OrdMap $ HM.singleton (keyOf x) (Indexed 0 (keyOf x) x)
instance (Eq k, Hashable k) => Selectable k a (OrdMap k a) where
selectOr fb f key OrdMap {mapEntries} = maybe fb (f . indexedValue) (HM.lookup key mapEntries)
instance (NameCollision a, Monad m, KeyOf k a, Failure ValidationErrors m) => SemigroupM m (OrdMap k a) where
mergeM ref (OrdMap x) (OrdMap y) = OrdMap <$> mergeM ref x y
instance (NameCollision a, Monad m, Failure ValidationErrors m, KeyOf k a, Hashable k) => FromElems m a (OrdMap k a) where
fromElems values = OrdMap <$> fromElems (indexed (toPair <$> values))
instance (Eq k, Hashable k) => Elems a (OrdMap k a) where
elems = getElements
unsafeFromList ::
(Hashable k, Eq k) =>
[(k, a)] ->
OrdMap k a
unsafeFromList = OrdMap . HM.fromList . fmap withKey . indexed
where
withKey idx = (indexedKey idx, idx)