diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | dependent-enummap.cabal | 18 | ||||
-rw-r--r-- | src/Data/Dependent/EnumMap/Strict.hs | 284 |
3 files changed, 303 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c33954f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dist-newstyle/ diff --git a/dependent-enummap.cabal b/dependent-enummap.cabal new file mode 100644 index 0000000..8b3839b --- /dev/null +++ b/dependent-enummap.cabal @@ -0,0 +1,18 @@ +cabal-version: 3.0 +name: dependent-enummap +version: 0.1.0.0 +license: BSD-3-Clause +author: Tom Smeding +build-type: Simple + +library + exposed-modules: + Data.Dependent.EnumMap.Strict + build-depends: + base >=4.15, + containers, + dependent-sum, + some + hs-source-dirs: src + default-language: Haskell2010 + ghc-options: -Wall diff --git a/src/Data/Dependent/EnumMap/Strict.hs b/src/Data/Dependent/EnumMap/Strict.hs new file mode 100644 index 0000000..6c1f11a --- /dev/null +++ b/src/Data/Dependent/EnumMap/Strict.hs @@ -0,0 +1,284 @@ +{-# LANGUAGE ExistentialQuantification #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +module Data.Dependent.EnumMap.Strict where + +import Data.Bifunctor (bimap) +import Data.Dependent.Sum +import qualified Data.IntMap.Strict as IM +import Data.Some +import Unsafe.Coerce (unsafeCoerce) + + +data KV k v = forall a. KV !(Enum1Info k) !(v a) + +newtype DEnumMap k v = DEnumMap (IM.IntMap (KV k v)) + +class Enum1 f where + type Enum1Info f + fromEnum1 :: f a -> (Int, Enum1Info f) + toEnum1 :: Int -> Enum1Info f -> Some f + +-- * Construction + +empty :: DEnumMap k v +empty = DEnumMap IM.empty + +singleton :: Enum1 k => k a -> v a -> DEnumMap k v +singleton k v = + let (i, inf) = fromEnum1 k + in DEnumMap (IM.singleton i (KV inf v)) + +-- fromSet + +-- ** From Unordered Lists + +fromList :: Enum1 k => [DSum k v] -> DEnumMap k v +fromList l = + DEnumMap (IM.fromList (map (\(k :=> v) -> let (i, inf) = fromEnum1 k in (i, KV inf v)) l)) + +-- fromListWith +-- fromListWithKey + +-- ** From Ascending Lists + +-- fromAscList +-- fromAscListWith +-- fromAscListWithKey + +fromDistinctAscList :: Enum1 k => [DSum k v] -> DEnumMap k v +fromDistinctAscList l = + DEnumMap (IM.fromDistinctAscList (map (\(k :=> v) -> let (i, inf) = fromEnum1 k in (i, KV inf v)) l)) + +-- * Insertion + +insert :: Enum1 k => k a -> v a -> DEnumMap k v -> DEnumMap k v +insert k v (DEnumMap m) = + let (i, inf) = fromEnum1 k + in DEnumMap (IM.insert i (KV inf v) m) + +-- insertWith + +insertWithKey :: Enum1 k + => (forall b. k b -> v b -> v b -> v b) + -> k a -> v a -> DEnumMap k v -> DEnumMap k v +insertWithKey f k v (DEnumMap m) = + let (i, inf) = fromEnum1 k + in DEnumMap (IM.insertWithKey + (\_ (KV _ v1) (KV _ v2) -> KV inf (f k (coe1 v1) (coe1 v2))) + i (KV inf v) m) + +-- insertLookupWithKey + +-- * Deletion\/Update + +delete :: Enum1 k => k a -> DEnumMap k v -> DEnumMap k v +delete k (DEnumMap m) = DEnumMap (IM.delete (fst (fromEnum1 k)) m) + +adjust :: Enum1 k => (v a -> v a) -> k a -> DEnumMap k v -> DEnumMap k v +adjust f k (DEnumMap m) = DEnumMap (IM.adjust (\(KV k' v) -> KV k' (f (coe1 v))) (fst (fromEnum1 k)) m) + +-- adjustWithKey +-- update +-- updateWithKey +-- updateLookupWithKey + +alter :: forall k v a. Enum1 k => (Maybe (v a) -> Maybe (v a)) -> k a -> DEnumMap k v -> DEnumMap k v +alter f k (DEnumMap m) = DEnumMap (IM.alter f' i m) + where + (i, inf) = fromEnum1 k + + f' :: Maybe (KV k v) -> Maybe (KV k v) + f' Nothing = KV inf <$> f Nothing + f' (Just (KV _ v)) = KV inf <$> f (Just (coe1 v)) + +-- alterF + +-- * Query +-- ** Lookup + +lookup :: Enum1 k => k a -> DEnumMap k v -> Maybe (v a) +lookup k (DEnumMap m) = (\(KV _ v) -> coe1 v) <$> IM.lookup (fst (fromEnum1 k)) m + +-- (!?) +-- (!) + +findWithDefault :: Enum1 k => v a -> k a -> DEnumMap k v -> v a +findWithDefault def k (DEnumMap m) = + (\(KV _ v) -> coe1 v) $ + IM.findWithDefault (KV undefined def) (fst (fromEnum1 k)) m + +member :: Enum1 k => k a -> DEnumMap k v -> Bool +member k (DEnumMap m) = IM.member (fst (fromEnum1 k)) m + +-- notMember +-- lookupLT +-- lookupGT +-- lookupLE +-- lookupGE + +-- ** Size + +null :: DEnumMap k v -> Bool +null (DEnumMap m) = IM.null m + +-- size + +-- * Combine + +-- ** Union + +union :: DEnumMap k v -> DEnumMap k v -> DEnumMap k v +union (DEnumMap m1) (DEnumMap m2) = DEnumMap (IM.union m1 m2) + +unionWith :: forall k v. (forall a. v a -> v a -> v a) + -> DEnumMap k v -> DEnumMap k v -> DEnumMap k v +unionWith f (DEnumMap m1) (DEnumMap m2) = DEnumMap (IM.unionWith f' m1 m2) + where + f' :: KV k v -> KV k v -> KV k v + f' (KV inf v1) (KV _ v2) = KV inf (f v1 (coe1 v2)) + +-- unionWithKey +-- unions +-- unionsWith + +-- ** Difference + +difference :: DEnumMap k v -> DEnumMap k v -> DEnumMap k v +difference (DEnumMap m1) (DEnumMap m2) = DEnumMap (IM.difference m1 m2) + +-- (\\) +-- differenceWith +-- differenceWithKey + +-- ** Intersection + +-- intersection +-- intersectionWith +-- intersectionWithKey + +-- ** Disjoint + +-- disjoint + +-- ** Compose + +-- compose + +-- ** Universal combining function + +-- mergeWithKey + +-- * Traversal +-- ** Map + +-- map +-- mapWithKey +-- traverseWithKey +-- traverseMaybeWithKey +-- mapAccum +-- mapAccumWithKey +-- mapAccumRWithKey +-- mapKeys +-- mapKeysWith +-- mapKeysMonotonic + +-- * Folds + +-- foldr +-- foldl +-- foldrWithKey +-- foldlWithKey +-- foldMapWithKey + +-- ** Strict folds + +-- foldr' +-- foldl' +-- foldrWithKey' +-- foldlWithKey' + +-- * Conversion + +elems :: DEnumMap k v -> [Some v] +elems (DEnumMap m) = map (\(KV _ v) -> Some v) (IM.elems m) + +keys :: Enum1 k => DEnumMap k v -> [Some k] +keys (DEnumMap m) = map (\(k, KV inf _) -> toEnum1 k inf) (IM.assocs m) + +-- assocs +-- keysSet + +-- ** Lists + +-- toList + +-- ** Ordered lists + +-- toAscList + +toDescList :: Enum1 k => DEnumMap k v -> [DSum k v] +toDescList (DEnumMap m) = + map (\(i, KV inf v) -> case toEnum1 i inf of Some k -> k :=> coe1 v) + (IM.toDescList m) + +-- * Filter + +-- filter +-- filterWithKey +-- restrictKeys +-- withoutKeys + +partition :: (forall a. v a -> Bool) -> DEnumMap k v -> (DEnumMap k v, DEnumMap k v) +partition f (DEnumMap m) = + bimap DEnumMap DEnumMap (IM.partition (\(KV _ v) -> f v) m) + +-- partitionWithKey + +-- takeWhileAntitone +-- dropWhileAntitone +-- spanAntitone + +-- mapMaybe +-- mapMaybeWithKey +-- mapEither +-- mapEitherWithKey + +-- split +-- splitLookup +-- splitRoot + +-- * Submap + +-- isSubmapOf, isSubmapOfBy +-- isProperSubmapOf, isProperSubmapOfBy + +-- * Min\/Max + +-- lookupMin +-- lookupMax +-- findMin +-- findMax +-- deleteMin +-- deleteMax +-- deleteFindMin +-- deleteFindMax +-- updateMin +-- updateMax +-- updateMinWithKey +-- updateMaxWithKey +-- minView +-- maxView +-- minViewWithKey + +maxViewWithKey :: Enum1 k => DEnumMap k v -> Maybe (DSum k v, DEnumMap k v) +maxViewWithKey (DEnumMap m) = + bimap (\(i, KV inf v) -> case toEnum1 i inf of Some k -> k :=> coe1 v) DEnumMap + <$> IM.maxViewWithKey m + + +-- * Unsafe helpers + +coe1 :: v a -> v b +coe1 = unsafeCoerce |