{-# language FlexibleContexts #-} {-# language GeneralizedNewtypeDeriving #-} {-# language PolyKinds #-} {-# language RankNTypes #-} {-# language TypeFamilies #-} module Data.Dependent.Map.Unboxed.Lifted ( Map , empty , null , singleton , lookup , foldrWithKey , foldlWithKeyM' , foldMapWithKey , traverseWithKey_ , toList , fromList , map , mapWithKey , mapMaybe , mapMaybeWithKey , size -- * Unsafe Functions , unsafeFreezeZip , unsafeCoerceKeys ) where import Prelude hiding (lookup,null,map) import Control.Monad.ST (ST) import Data.Aeson (FromJSON,ToJSON) import Data.Dependent.Map.Class (Universally,ApplyUniversally) import Data.Exists (EqForallPoly,EqForeach,OrdForeach) import Data.Exists (OrdForallPoly,DependentPair,ShowForall,ShowForeach,ToSing) import Data.Exists (ToJSONKeyForall,FromJSONKeyExists,ToJSONForeach,SemigroupForeach) import Data.Exists (FromJSONForeach) import Data.Primitive (Array,PrimArray,Prim,MutablePrimArray,MutableArray) import Data.Proxy (Proxy) import Data.Semigroup (Semigroup) import GHC.Exts (IsList,Any) import Unsafe.Coerce (unsafeCoerce) import qualified Data.Aeson as AE import qualified Data.Semigroup as SG import qualified Data.Dependent.Map.Internal as I import qualified GHC.Exts import qualified Data.Set.Unboxed.Internal as SU import qualified Data.Map.Internal as M newtype Map k v = Map (I.Map PrimArray Array k v) empty :: Map k v empty = Map I.empty null :: Map k v -> Bool null (Map m) = I.null m singleton :: Universally k Prim => k a -> v a -> Map k v singleton f v = Map (I.singleton f v) lookup :: (Universally k Prim, ApplyUniversally k Prim, OrdForallPoly k) => k a -> Map k v -> Maybe (v a) lookup k (Map x) = I.lookup k x fromList :: (Universally k Prim, ApplyUniversally k Prim, OrdForallPoly k) => [DependentPair k v] -> Map k v fromList xs = Map (I.fromList xs) fromListN :: (Universally k Prim, ApplyUniversally k Prim, OrdForallPoly k) => Int -> [DependentPair k v] -> Map k v fromListN n xs = Map (I.fromListN n xs) toList :: Universally k Prim => Map k v -> [DependentPair k v] toList (Map x) = I.toList x size :: Map k v -> Int size (Map x) = I.size x foldrWithKey :: Universally k Prim => (forall a. k a -> v a -> b -> b) -> b -> Map k v -> b foldrWithKey f b (Map m) = I.foldrWithKey f b m foldlWithKeyM' :: (Universally k Prim, Monad m) => (forall a. b -> k a -> v a -> m b) -> b -> Map k v -> m b foldlWithKeyM' f b (Map m) = I.foldlWithKeyM' f b m foldMapWithKey :: (Universally k Prim, Monoid m) => (forall a. k a -> v a -> m) -> Map k v -> m foldMapWithKey f (Map m) = I.foldMapWithKey f m traverseWithKey_ :: (Universally k Prim, Applicative m) => (forall a. k a -> v a -> m b) -> Map k v -> m () traverseWithKey_ f (Map m) = I.traverseWithKey_ f m map :: Universally k Prim => (forall a. v a -> w a) -> Map k v -> Map k w map f (Map m) = Map (I.map f m) mapMaybe :: Universally k Prim => (forall a. v a -> Maybe (w a)) -> Map k v -> Map k w mapMaybe f (Map m) = Map (I.mapMaybe f m) mapMaybeWithKey :: Universally k Prim => (forall a. k a -> v a -> Maybe (w a)) -> Map k v -> Map k w mapMaybeWithKey f (Map m) = Map (I.mapMaybeWithKey f m) mapWithKey :: Universally k Prim => (forall a. k a -> v a -> w a) -> Map k v -> Map k w mapWithKey f (Map m) = Map (I.mapWithKey f m) -- | This function is even more unsafe than the @unsafeFreezeZip@ provided by -- @Data.Map.Unboxed.Lifted@. The user needs to use @unsafeCoerce@ to even use this -- function. unsafeFreezeZip :: (Universally k Prim, OrdForallPoly k) => MutablePrimArray s (k Any) -> MutableArray s (v Any) -> ST s (Map k v) {-# INLINABLE unsafeFreezeZip #-} unsafeFreezeZip keys0 vals0 = fmap Map (I.unsafeFreezeZip keys0 vals0) -- | /O(1)/ This function is highly unsafe. The user is responsible for ensuring -- that: -- -- * Both @k'@ and @forall a. k a@ have the same runtime representation. -- * The @Ord@ instance for @k'@ agrees with the @OrdForallPoly@ instance -- for @k@. unsafeCoerceKeys :: Proxy k' -> Map k v -> SU.Set k' unsafeCoerceKeys p (Map (I.Map m)) = -- TODO: Technical debt. Add this function to the Internal module -- so that the data constructor does not have to be exported. unsafeCoerceSet p (SU.Set (M.keys m)) unsafeCoerceSet :: Proxy k' -> SU.Set (k Any) -> SU.Set k' unsafeCoerceSet _ = unsafeCoerce instance (Universally k Prim, ApplyUniversally k Prim, OrdForallPoly k) => IsList (Map k v) where type Item (Map k v) = DependentPair k v fromListN = fromListN fromList = fromList toList = toList instance (Universally k Prim, ApplyUniversally k Prim, ShowForall k, ToSing k, ShowForeach v) => Show (Map k v) where showsPrec p (Map s) = I.showsPrec p s instance (Universally k Prim, ApplyUniversally k Prim, EqForallPoly k, ToSing k, EqForeach v) => Eq (Map k v) where Map x == Map y = I.equals x y instance (Universally k Prim, ApplyUniversally k Prim, OrdForallPoly k, ToSing k, OrdForeach v) => Ord (Map k v) where compare (Map x) (Map y) = I.compare x y instance (Universally k Prim, ToSing k, ToJSONKeyForall k, ToJSONForeach v) => ToJSON (Map k v) where toJSON (Map m) = I.toJSON m instance (Universally k Prim, ApplyUniversally k Prim, ToSing k, FromJSONKeyExists k, FromJSONForeach v, OrdForallPoly k) => FromJSON (Map k v) where parseJSON v = fmap Map (I.parseJSON v) instance (ApplyUniversally k Prim, Universally k Prim, ToSing k, OrdForallPoly k, SemigroupForeach v) => Semigroup (Map k v) where Map x <> Map y = Map (I.append x y) instance (ApplyUniversally k Prim, Universally k Prim, ToSing k, OrdForallPoly k, SemigroupForeach v) => Monoid (Map k v) where mempty = Map I.empty mappend = (SG.<>)