packages feed

enummapmap 0.1.0 → 0.2.0

raw patch · 9 files changed

+1120/−691 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.EnumMapMap.Lazy: data K k
- Data.EnumMapMap.Lazy: instance Enum k => IsEmm (K k)
- Data.EnumMapMap.Strict: data K k
- Data.EnumMapMap.Strict: instance Enum k => IsEmm (K k)
- Data.EnumMapSet: K :: !k -> K k
- Data.EnumMapSet: data K k
- Data.EnumMapSet: instance Enum k => IsEmm (K k)
+ Data.EnumMapMap.Lazy: elems :: IsKey k => EnumMapMap k v -> [v]
+ Data.EnumMapMap.Lazy: instance (Enum k, Eq k) => IsKey (K k)
+ Data.EnumMapMap.Lazy: instance (Enum k1, k1 ~ k2) => SubKey (K k1) (k2 :& t2) v
+ Data.EnumMapMap.Lazy: instance Enum k => SubKey (K k) (K k) v
+ Data.EnumMapMap.Lazy: instance Eq k => Eq (K k)
+ Data.EnumMapMap.Lazy: instance HasSKey (K k)
+ Data.EnumMapMap.Lazy: instance Show k => Show (K k)
+ Data.EnumMapMap.Lazy: keys :: IsKey k => EnumMapMap k v -> [k]
+ Data.EnumMapMap.Lazy: keysSet :: (IsKey k, HasSKey k) => EnumMapMap k v -> EnumMapMap (Skey k) ()
+ Data.EnumMapMap.Lazy: newtype K k
+ Data.EnumMapMap.Lazy: toK :: HasSKey k => Skey k -> k
+ Data.EnumMapMap.Lazy: toS :: HasSKey k => k -> Skey k
+ Data.EnumMapMap.Strict: elems :: IsKey k => EnumMapMap k v -> [v]
+ Data.EnumMapMap.Strict: instance (Enum k, Eq k) => IsKey (K k)
+ Data.EnumMapMap.Strict: instance (Enum k1, k1 ~ k2) => SubKey (K k1) (k2 :& t2) v
+ Data.EnumMapMap.Strict: instance Enum k => SubKey (K k) (K k) v
+ Data.EnumMapMap.Strict: instance Eq k => Eq (K k)
+ Data.EnumMapMap.Strict: instance HasSKey (K k)
+ Data.EnumMapMap.Strict: instance Show k => Show (K k)
+ Data.EnumMapMap.Strict: keys :: IsKey k => EnumMapMap k v -> [k]
+ Data.EnumMapMap.Strict: keysSet :: (IsKey k, HasSKey k) => EnumMapMap k v -> EnumMapMap (Skey k) ()
+ Data.EnumMapMap.Strict: newtype K k
+ Data.EnumMapMap.Strict: toK :: HasSKey k => Skey k -> k
+ Data.EnumMapMap.Strict: toS :: HasSKey k => k -> Skey k
+ Data.EnumMapSet: S :: k -> S k
+ Data.EnumMapSet: keys :: IsKey k => EnumMapSet k -> [k]
+ Data.EnumMapSet: lookup :: (SubKey k1 k2 (), IsKey k1, IsKey k2) => k1 -> EnumMapSet k2 -> Maybe (Result k1 k2 ())
+ Data.EnumMapSet: newtype S k
- Data.EnumMapMap.Lazy: K :: !k -> K k
+ Data.EnumMapMap.Lazy: K :: k -> K k
- Data.EnumMapMap.Lazy: alter :: IsEmm k => (Maybe v -> Maybe v) -> k -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: alter :: IsKey k => (Maybe v -> Maybe v) -> k -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Lazy: d10 :: N (N (N (N (N (N (N (N (N (Z)))))))))
+ Data.EnumMapMap.Lazy: d10 :: N (N (N (N (N (N (N (N (N Z))))))))
- Data.EnumMapMap.Lazy: d2 :: N (Z)
+ Data.EnumMapMap.Lazy: d2 :: N Z
- Data.EnumMapMap.Lazy: d3 :: N (N (Z))
+ Data.EnumMapMap.Lazy: d3 :: N (N Z)
- Data.EnumMapMap.Lazy: d4 :: N (N (N (Z)))
+ Data.EnumMapMap.Lazy: d4 :: N (N (N Z))
- Data.EnumMapMap.Lazy: d5 :: N (N (N (N (Z))))
+ Data.EnumMapMap.Lazy: d5 :: N (N (N (N Z)))
- Data.EnumMapMap.Lazy: d6 :: N (N (N (N (N (Z)))))
+ Data.EnumMapMap.Lazy: d6 :: N (N (N (N (N Z))))
- Data.EnumMapMap.Lazy: d7 :: N (N (N (N (N (N (Z))))))
+ Data.EnumMapMap.Lazy: d7 :: N (N (N (N (N (N Z)))))
- Data.EnumMapMap.Lazy: d8 :: N (N (N (N (N (N (N (Z)))))))
+ Data.EnumMapMap.Lazy: d8 :: N (N (N (N (N (N (N Z))))))
- Data.EnumMapMap.Lazy: d9 :: N (N (N (N (N (N (N (N (Z))))))))
+ Data.EnumMapMap.Lazy: d9 :: N (N (N (N (N (N (N (N Z)))))))
- Data.EnumMapMap.Lazy: delete :: IsEmm k => k -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: delete :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Lazy: difference :: IsEmm k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Lazy: difference :: IsKey k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Lazy: differenceWith :: IsEmm k => (v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Lazy: differenceWith :: IsKey k => (v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Lazy: differenceWithKey :: IsEmm k => (k -> v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Lazy: differenceWithKey :: IsKey k => (k -> v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Lazy: empty :: IsEmm k => EnumMapMap k v
+ Data.EnumMapMap.Lazy: empty :: IsKey k => EnumMapMap k v
- Data.EnumMapMap.Lazy: emptySubTrees :: IsEmm k => EnumMapMap k v -> Bool
+ Data.EnumMapMap.Lazy: emptySubTrees :: IsKey k => EnumMapMap k v -> Bool
- Data.EnumMapMap.Lazy: foldr :: IsEmm k => (v -> t -> t) -> t -> EnumMapMap k v -> t
+ Data.EnumMapMap.Lazy: foldr :: IsKey k => (v -> t -> t) -> t -> EnumMapMap k v -> t
- Data.EnumMapMap.Lazy: foldrWithKey :: IsEmm k => (k -> v -> t -> t) -> t -> EnumMapMap k v -> t
+ Data.EnumMapMap.Lazy: foldrWithKey :: IsKey k => (k -> v -> t -> t) -> t -> EnumMapMap k v -> t
- Data.EnumMapMap.Lazy: fromList :: IsEmm k => [(k, v)] -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: fromList :: (IsKey k, SubKey k k v, Result k k v ~ v) => [(k, v)] -> EnumMapMap k v
- Data.EnumMapMap.Lazy: insert :: IsEmm k => k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: insert :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Lazy: insertWith :: IsEmm k => (v -> v -> v) -> k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: insertWith :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => (Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v) -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Lazy: insertWithKey :: IsEmm k => (k -> v -> v -> v) -> k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: insertWithKey :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => (k1 -> Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v) -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Lazy: intersection :: IsEmm k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Lazy: intersection :: IsKey k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Lazy: intersectionWith :: IsEmm k => (v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
+ Data.EnumMapMap.Lazy: intersectionWith :: IsKey k => (v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
- Data.EnumMapMap.Lazy: intersectionWithKey :: IsEmm k => (k -> v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
+ Data.EnumMapMap.Lazy: intersectionWithKey :: IsKey k => (k -> v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
- Data.EnumMapMap.Lazy: joinKey :: (IsEmm k, IsEmm (Plus k k2)) => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
+ Data.EnumMapMap.Lazy: joinKey :: (IsKey k, IsKey (Plus k k2)) => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
- Data.EnumMapMap.Lazy: lookup :: IsEmm k => k -> EnumMapMap k v -> Maybe v
+ Data.EnumMapMap.Lazy: lookup :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> EnumMapMap k2 v -> Maybe (Result k1 k2 v)
- Data.EnumMapMap.Lazy: map :: IsEmm k => (v -> t) -> EnumMapMap k v -> EnumMapMap k t
+ Data.EnumMapMap.Lazy: map :: IsKey k => (v -> t) -> EnumMapMap k v -> EnumMapMap k t
- Data.EnumMapMap.Lazy: mapWithKey :: IsEmm k => (k -> v -> t) -> EnumMapMap k v -> EnumMapMap k t
+ Data.EnumMapMap.Lazy: mapWithKey :: IsKey k => (k -> v -> t) -> EnumMapMap k v -> EnumMapMap k t
- Data.EnumMapMap.Lazy: member :: IsEmm k => k -> EnumMapMap k v -> Bool
+ Data.EnumMapMap.Lazy: member :: IsKey k => k -> EnumMapMap k v -> Bool
- Data.EnumMapMap.Lazy: null :: IsEmm k => EnumMapMap k v -> Bool
+ Data.EnumMapMap.Lazy: null :: IsKey k => EnumMapMap k v -> Bool
- Data.EnumMapMap.Lazy: singleton :: IsEmm k => k -> v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: singleton :: SubKey k1 k2 v => k1 -> Result k1 k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Lazy: size :: IsEmm k => EnumMapMap k v -> Int
+ Data.EnumMapMap.Lazy: size :: IsKey k => EnumMapMap k v -> Int
- Data.EnumMapMap.Lazy: toList :: IsEmm k => EnumMapMap k v -> [(k, v)]
+ Data.EnumMapMap.Lazy: toList :: (IsKey k, SubKey k k v) => EnumMapMap k v -> [(k, v)]
- Data.EnumMapMap.Lazy: union :: IsEmm k => EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: union :: IsKey k => EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Lazy: unionWith :: IsEmm k => (v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: unionWith :: IsKey k => (v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Lazy: unionWithKey :: IsEmm k => (k -> v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: unionWithKey :: IsKey k => (k -> v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Lazy: unions :: IsEmm k => [EnumMapMap k v] -> EnumMapMap k v
+ Data.EnumMapMap.Lazy: unions :: IsKey k => [EnumMapMap k v] -> EnumMapMap k v
- Data.EnumMapMap.Lazy: unsafeJoinKey :: IsEmm k => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
+ Data.EnumMapMap.Lazy: unsafeJoinKey :: IsKey k => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
- Data.EnumMapMap.Strict: K :: !k -> K k
+ Data.EnumMapMap.Strict: K :: k -> K k
- Data.EnumMapMap.Strict: alter :: IsEmm k => (Maybe v -> Maybe v) -> k -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: alter :: IsKey k => (Maybe v -> Maybe v) -> k -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Strict: d10 :: N (N (N (N (N (N (N (N (N (Z)))))))))
+ Data.EnumMapMap.Strict: d10 :: N (N (N (N (N (N (N (N (N Z))))))))
- Data.EnumMapMap.Strict: d2 :: N (Z)
+ Data.EnumMapMap.Strict: d2 :: N Z
- Data.EnumMapMap.Strict: d3 :: N (N (Z))
+ Data.EnumMapMap.Strict: d3 :: N (N Z)
- Data.EnumMapMap.Strict: d4 :: N (N (N (Z)))
+ Data.EnumMapMap.Strict: d4 :: N (N (N Z))
- Data.EnumMapMap.Strict: d5 :: N (N (N (N (Z))))
+ Data.EnumMapMap.Strict: d5 :: N (N (N (N Z)))
- Data.EnumMapMap.Strict: d6 :: N (N (N (N (N (Z)))))
+ Data.EnumMapMap.Strict: d6 :: N (N (N (N (N Z))))
- Data.EnumMapMap.Strict: d7 :: N (N (N (N (N (N (Z))))))
+ Data.EnumMapMap.Strict: d7 :: N (N (N (N (N (N Z)))))
- Data.EnumMapMap.Strict: d8 :: N (N (N (N (N (N (N (Z)))))))
+ Data.EnumMapMap.Strict: d8 :: N (N (N (N (N (N (N Z))))))
- Data.EnumMapMap.Strict: d9 :: N (N (N (N (N (N (N (N (Z))))))))
+ Data.EnumMapMap.Strict: d9 :: N (N (N (N (N (N (N (N Z)))))))
- Data.EnumMapMap.Strict: delete :: IsEmm k => k -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: delete :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Strict: difference :: IsEmm k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Strict: difference :: IsKey k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Strict: differenceWith :: IsEmm k => (v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Strict: differenceWith :: IsKey k => (v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Strict: differenceWithKey :: IsEmm k => (k -> v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Strict: differenceWithKey :: IsKey k => (k -> v1 -> v2 -> Maybe v1) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Strict: empty :: IsEmm k => EnumMapMap k v
+ Data.EnumMapMap.Strict: empty :: IsKey k => EnumMapMap k v
- Data.EnumMapMap.Strict: emptySubTrees :: IsEmm k => EnumMapMap k v -> Bool
+ Data.EnumMapMap.Strict: emptySubTrees :: IsKey k => EnumMapMap k v -> Bool
- Data.EnumMapMap.Strict: foldr :: IsEmm k => (v -> t -> t) -> t -> EnumMapMap k v -> t
+ Data.EnumMapMap.Strict: foldr :: IsKey k => (v -> t -> t) -> t -> EnumMapMap k v -> t
- Data.EnumMapMap.Strict: foldrWithKey :: IsEmm k => (k -> v -> t -> t) -> t -> EnumMapMap k v -> t
+ Data.EnumMapMap.Strict: foldrWithKey :: IsKey k => (k -> v -> t -> t) -> t -> EnumMapMap k v -> t
- Data.EnumMapMap.Strict: fromList :: IsEmm k => [(k, v)] -> EnumMapMap k v
+ Data.EnumMapMap.Strict: fromList :: (IsKey k, SubKey k k v, Result k k v ~ v) => [(k, v)] -> EnumMapMap k v
- Data.EnumMapMap.Strict: insert :: IsEmm k => k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: insert :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Strict: insertWith :: IsEmm k => (v -> v -> v) -> k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: insertWith :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => (Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v) -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Strict: insertWithKey :: IsEmm k => (k -> v -> v -> v) -> k -> v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: insertWithKey :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => (k1 -> Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v) -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Strict: intersection :: IsEmm k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
+ Data.EnumMapMap.Strict: intersection :: IsKey k => EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v1
- Data.EnumMapMap.Strict: intersectionWith :: IsEmm k => (v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
+ Data.EnumMapMap.Strict: intersectionWith :: IsKey k => (v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
- Data.EnumMapMap.Strict: intersectionWithKey :: IsEmm k => (k -> v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
+ Data.EnumMapMap.Strict: intersectionWithKey :: IsKey k => (k -> v1 -> v2 -> v3) -> EnumMapMap k v1 -> EnumMapMap k v2 -> EnumMapMap k v3
- Data.EnumMapMap.Strict: joinKey :: (IsEmm k, IsEmm (Plus k k2)) => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
+ Data.EnumMapMap.Strict: joinKey :: (IsKey k, IsKey (Plus k k2)) => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
- Data.EnumMapMap.Strict: lookup :: IsEmm k => k -> EnumMapMap k v -> Maybe v
+ Data.EnumMapMap.Strict: lookup :: (SubKey k1 k2 v, IsKey k1, IsKey k2) => k1 -> EnumMapMap k2 v -> Maybe (Result k1 k2 v)
- Data.EnumMapMap.Strict: map :: IsEmm k => (v -> t) -> EnumMapMap k v -> EnumMapMap k t
+ Data.EnumMapMap.Strict: map :: IsKey k => (v -> t) -> EnumMapMap k v -> EnumMapMap k t
- Data.EnumMapMap.Strict: mapWithKey :: IsEmm k => (k -> v -> t) -> EnumMapMap k v -> EnumMapMap k t
+ Data.EnumMapMap.Strict: mapWithKey :: IsKey k => (k -> v -> t) -> EnumMapMap k v -> EnumMapMap k t
- Data.EnumMapMap.Strict: member :: IsEmm k => k -> EnumMapMap k v -> Bool
+ Data.EnumMapMap.Strict: member :: IsKey k => k -> EnumMapMap k v -> Bool
- Data.EnumMapMap.Strict: null :: IsEmm k => EnumMapMap k v -> Bool
+ Data.EnumMapMap.Strict: null :: IsKey k => EnumMapMap k v -> Bool
- Data.EnumMapMap.Strict: singleton :: IsEmm k => k -> v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: singleton :: SubKey k1 k2 v => k1 -> Result k1 k2 v -> EnumMapMap k2 v
- Data.EnumMapMap.Strict: size :: IsEmm k => EnumMapMap k v -> Int
+ Data.EnumMapMap.Strict: size :: IsKey k => EnumMapMap k v -> Int
- Data.EnumMapMap.Strict: toList :: IsEmm k => EnumMapMap k v -> [(k, v)]
+ Data.EnumMapMap.Strict: toList :: (IsKey k, SubKey k k v) => EnumMapMap k v -> [(k, v)]
- Data.EnumMapMap.Strict: union :: IsEmm k => EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: union :: IsKey k => EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Strict: unionWith :: IsEmm k => (v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: unionWith :: IsKey k => (v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Strict: unionWithKey :: IsEmm k => (k -> v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
+ Data.EnumMapMap.Strict: unionWithKey :: IsKey k => (k -> v -> v -> v) -> EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v
- Data.EnumMapMap.Strict: unions :: IsEmm k => [EnumMapMap k v] -> EnumMapMap k v
+ Data.EnumMapMap.Strict: unions :: IsKey k => [EnumMapMap k v] -> EnumMapMap k v
- Data.EnumMapMap.Strict: unsafeJoinKey :: IsEmm k => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
+ Data.EnumMapMap.Strict: unsafeJoinKey :: IsKey k => EnumMapMap k (EnumMapMap k2 v) -> EnumMapMap (Plus k k2) v
- Data.EnumMapSet: delete :: IsEmm k => k -> EnumMapSet k -> EnumMapSet k
+ Data.EnumMapSet: delete :: (SubKey k1 k2 (), IsKey k1, IsKey k2) => k1 -> EnumMapSet k2 -> EnumMapSet k2
- Data.EnumMapSet: difference :: IsEmm k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k
+ Data.EnumMapSet: difference :: IsKey k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k
- Data.EnumMapSet: empty :: IsEmm k => EnumMapSet k
+ Data.EnumMapSet: empty :: IsKey k => EnumMapSet k
- Data.EnumMapSet: foldr :: IsEmm k => (k -> t -> t) -> t -> EnumMapSet k -> t
+ Data.EnumMapSet: foldr :: IsKey k => (k -> t -> t) -> t -> EnumMapSet k -> t
- Data.EnumMapSet: fromList :: IsEmm k => [k] -> EnumMapSet k
+ Data.EnumMapSet: fromList :: (IsKey k, SubKey k k (), Result k k () ~ ()) => [k] -> EnumMapSet k
- Data.EnumMapSet: insert :: IsEmm k => k -> EnumMapSet k -> EnumMapSet k
+ Data.EnumMapSet: insert :: (IsKey k, SubKey k k (), Result k k () ~ ()) => k -> EnumMapSet k -> EnumMapSet k
- Data.EnumMapSet: intersection :: IsEmm k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k
+ Data.EnumMapSet: intersection :: IsKey k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k
- Data.EnumMapSet: map :: (IsEmm k1, IsEmm k2) => (k1 -> k2) -> EnumMapSet k1 -> EnumMapSet k2
+ Data.EnumMapSet: map :: (IsKey k1, IsKey k2, SubKey k2 k2 (), Result k2 k2 () ~ ()) => (k1 -> k2) -> EnumMapSet k1 -> EnumMapSet k2
- Data.EnumMapSet: member :: IsEmm k => k -> EnumMapSet k -> Bool
+ Data.EnumMapSet: member :: IsKey k => k -> EnumMapSet k -> Bool
- Data.EnumMapSet: null :: IsEmm k => EnumMapSet k -> Bool
+ Data.EnumMapSet: null :: IsKey k => EnumMapSet k -> Bool
- Data.EnumMapSet: singleton :: IsEmm k => k -> EnumMapSet k
+ Data.EnumMapSet: singleton :: (IsKey k, SubKey k k (), Result k k () ~ ()) => k -> EnumMapSet k
- Data.EnumMapSet: size :: IsEmm k => EnumMapSet k -> Int
+ Data.EnumMapSet: size :: IsKey k => EnumMapSet k -> Int
- Data.EnumMapSet: toList :: IsEmm k => EnumMapSet k -> [k]
+ Data.EnumMapSet: toList :: IsKey k => EnumMapSet k -> [k]
- Data.EnumMapSet: union :: IsEmm k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k
+ Data.EnumMapSet: union :: IsKey k => EnumMapSet k -> EnumMapSet k -> EnumMapSet k

Files

Data/EnumMapMap/Base.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE MagicHash, TypeFamilies, MultiParamTypeClasses,     BangPatterns, FlexibleInstances, TypeOperators,-    FlexibleContexts #-}+    FlexibleContexts, GeneralizedNewtypeDeriving #-}  ----------------------------------------------------------------------------- -- |@@ -9,29 +9,31 @@ --                (c) Andriy Palamarchuk 2008 --                (c) Matthew West 2012 -- License     :  BSD-style--- Maintainer  : -- Stability   :  experimental -- Portability :  Uses GHC extensions -- -- Based on Data.IntMap.Base. ----- This defines the EnumMapMap (k :& t) v instance, and the Key data types.  The--- terminating key type is K, and the EnumMapMap (K k) v instances are defined+-- This defines the @'EnumMapMap' (k ':&' t) v@ instance, and the Key data types.  The+-- terminating key type is K, and the @'EnumMapMap' (K k) v@ instances are defined -- in EnumMapMap.Lazy and EnumMapMap.Strict. -----------------------------------------------------------------------------  module Data.EnumMapMap.Base(             -- * Key types-            (:&)(..), K(..), N(..), Z(..),+            (:&)(..), N(..), Z(..),             d1, d2, d3, d4, d5, d6, d7, d8, d9, d10,             -- * Split/Join Keys             IsSplit(..),             Plus,+            SubKey(..),             -- * Internal             -- ** IsEMM             EMM(..),-            IsEmm(..),+            IsKey(..),             EnumMapMap(..),+            -- ** SKey+            HasSKey(..),             -- ** EMM internals             mergeWithKey',             mapWithKey_,@@ -45,6 +47,8 @@             intFromNat,             shiftRL,             shiftLL,+            branchMask,+            mask,             bin,             tip,             shorter,@@ -79,22 +83,16 @@ type Mask   = Int  infixr 3 :&--- | Multiple keys are joined by the (':&') constructor and terminated with 'K'.+-- | Multiple keys are joined by the (':&') constructor. -- -- > multiKey :: Int :& Int :& K Int -- > multiKey = 5 :& 6 :& K 5 -- data k :& t = !k :& !t                    deriving (Show, Eq)--- | Keys are terminated with the 'K' type------ > singleKey :: K Int--- > singleKey = K 5----data K k = K !k-           deriving (Show, Eq)+ data Z = Z-data N n = N n+data N n = N !n  -- | Split after 1 key. --@@ -106,23 +104,23 @@ -- -- > emm :: EnumMapMap (T1 :& T2 :& K T3) v -- > splitKey d1 emm :: EnumMapMap (K T1) (EnumMapMap (T2 :& K T3) v)-d2 ::  N(Z)+d2 ::  N Z d2  =  N d1-d3 ::  N(N(Z))+d3 ::  N(N Z) d3  =  N d2-d4 ::  N(N(N(Z)))+d4 ::  N(N(N Z)) d4  =  N d3-d5 ::  N(N(N(N(Z))))+d5 ::  N(N(N(N Z))) d5  =  N d4-d6 ::  N(N(N(N(N(Z)))))+d6 ::  N(N(N(N(N Z)))) d6  =  N d5-d7 ::  N(N(N(N(N(N(Z))))))+d7 ::  N(N(N(N(N(N Z))))) d7  =  N d6-d8 ::  N(N(N(N(N(N(N(Z)))))))+d8 ::  N(N(N(N(N(N(N Z)))))) d8  =  N d7-d9 ::  N(N(N(N(N(N(N(N(Z))))))))+d9 ::  N(N(N(N(N(N(N(N Z))))))) d9  =  N d8-d10 :: N(N(N(N(N(N(N(N(N(Z)))))))))+d10 :: N(N(N(N(N(N(N(N(N Z)))))))) d10 =  N d9  class IsSplit k z where@@ -147,14 +145,101 @@              -> EnumMapMap (Head k z) (EnumMapMap (Tail k z) v)  instance (IsSplit t n, Enum k) => IsSplit (k :& t) (N n) where-    type Head (k :& t) (N n) = k :& (Head t n)+    type Head (k :& t) (N n) = k :& Head t n     type Tail (k :& t) (N n) = Tail t n     splitKey (N n) (KCC emm) = KCC $ mapWithKey_ (\_ -> splitKey n) emm  type family Plus k1 k2 :: *-type instance Plus (k1 :& t) k2 = k1 :& (Plus t k2)+type instance Plus (k1 :& t) k2 = k1 :& Plus t k2 -class IsEmm k where+class SubKey k1 k2 v where+    -- k1 should be a prefix of k2.  If @k1 ~ k2@ then the 'Result' will be @v@.+    type Result k1 k2 v :: *+    -- | An 'EnumMapMap' with one element+    --+    -- > singleton (5 :& K 3) "a" == fromList [(5 :& K 3, "a")]+    -- > singleton (K 5) $ singleton (K 2) "a" == fromList [(5 :& K 3, "a")]+    singleton :: k1 -> Result k1 k2 v -> EnumMapMap k2 v+    -- | Lookup up the value at a key in the 'EnumMapMap'.+    --+    -- > emm = fromList [(3 :& K 1, "a")]+    -- > lookup (3 :& K 1) emm == Just "a"+    -- > lookup (2 :& K 1) emm == Nothing+    --+    -- If the given key has less dimensions then the 'EnumMapMap' then a submap+    -- is returned.+    --+    -- > emm2 = fromList [(3 :& 2 :& K 1, "a"), (3 :& 2 :& K 4, "a")]+    -- > lookup (3 :& K 2) emm2 == Just $ fromList [(K 1, "a"), (K 4, "a")]+    --+    lookup :: (IsKey k1, IsKey k2) =>+              k1 -> EnumMapMap k2 v -> Maybe (Result k1 k2 v)+    -- | Insert a new key\/value pair into the 'EnumMapMap'.  Can also insert submaps.+    insert :: (IsKey k1, IsKey k2) =>+               k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v+    -- | Insert with a combining function.  Can also insert submaps.+    insertWith :: (IsKey k1, IsKey k2) =>+                  (Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v)+               -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v+    insertWith f = insertWithKey (\_ -> f)+    -- | Insert with a combining function.  Can also insert submaps.+    insertWithKey :: (IsKey k1, IsKey k2) =>+                     (k1 -> Result k1 k2 v -> Result k1 k2 v -> Result k1 k2 v)+                  -> k1 -> Result k1 k2 v -> EnumMapMap k2 v -> EnumMapMap k2 v+    -- | Remove a key and it's value from the 'EnumMapMap'.  If the key is not+    -- present the original 'EnumMapMap' is returned.+    delete :: (IsKey k1, IsKey k2) =>+              k1 -> EnumMapMap k2 v -> EnumMapMap k2 v++instance (Enum k, IsKey t1, IsKey t2, SubKey t1 t2 v) =>+    SubKey (k :& t1) (k :& t2) v where+    type Result (k :& t1) (k :& t2) v = Result t1 t2 v++    singleton (key :& nxt) = KCC . Tip (fromEnum key) . singleton nxt++    lookup !(key' :& nxt) (KCC emm) = key `seq` go emm+        where+          go (Bin _ m l r)+             | zero key m = go l+             | otherwise = go r+          go (Tip kx x)+             = case kx == key of+                 True -> lookup nxt x+                 False -> Nothing+          go Nil = Nothing+          key = fromEnum key'++    insert (key :& nxt) val (KCC emm) =+        KCC $ insertWith_ (insert nxt val) key (singleton nxt val) emm++    insertWithKey f k@(key :& nxt) val (KCC emm) =+        KCC $ insertWith_ go key (singleton nxt val) emm+            where+              go = insertWithKey (\_ -> f k) nxt val++    delete !(key :& nxt) (KCC emm) =+        KCC $ alter_ (delete nxt) (fromEnum key) emm++class HasSKey k where+    type Skey k :: *+    -- | Convert a key terminated with 'K' into one terminated with 'S'.+    --+    -- > k = 1 :& 2 :& 'K' 3+    -- > toS k == 1 :& 2 :& 'S' 3+    --+    toS :: k -> Skey k+    -- | Convert a key terminated with 'S' into one terminated with 'K'.+    --+    -- > s = 1 :& 2 :& S 3+    -- > toK s == 1 :& 2 :& K 3+    toK :: Skey k -> k++instance (HasSKey t) => HasSKey (k :& t) where+    type Skey (k :& t) = k :& (Skey t)+    toS (k :& t) = (:&) k $! toS t+    toK (k :& t) = (:&) k $! toK t++class (Eq k) => IsKey k where     -- | A map of keys to values.  The keys are 'Enum' types but are stored as 'Int's     -- so any keys with the same 'Int' value are treated as the same.  The aim is to     -- provide typesafe indexing.@@ -164,10 +249,11 @@     emptySubTrees  :: EnumMapMap k v -> Bool     emptySubTrees_ :: EnumMapMap k v -> Bool +    -- | Remove empty subtrees.     removeEmpties :: EnumMapMap k v -> EnumMapMap k v -    -- | Join a key so that an 'EnumMapMap' of-    -- 'EnumMapMap's becomes an 'EnumMapMap'.+    -- | Join a key so that an 'EnumMapMap' of 'EnumMapMap's becomes an+    -- 'EnumMapMap'.     --     -- > newtype ID = ID Int deriving Enum     -- > emm :: EnumMapMap (K Int) (EnumMapMap (K ID) Bool)@@ -179,14 +265,14 @@     -- > emm = empty :: EnumMapMap (Int :& Int :& K ID) Bool)     -- > emm == joinKey $ splitKey d2 emm     ---    joinKey :: (IsEmm (Plus k k2)) =>+    joinKey :: (IsKey (Plus k k2)) =>                EnumMapMap k (EnumMapMap k2 v)             -> EnumMapMap (Plus k k2) v     joinKey = removeEmpties . unsafeJoinKey -    -- | Join a key so that an 'EnumMapMap' of-    -- 'EnumMapMap's becomes an 'EnumMapMap'.  The unsafe version does not check-    -- for empty subtrees, so it is faster.+    -- | Join a key so that an 'EnumMapMap' of 'EnumMapMap's becomes an+    -- 'EnumMapMap'.  The unsafe version does not check for empty subtrees, so+    -- it is faster.     --     -- > newtype ID = ID Int deriving Enum     -- > emm :: EnumMapMap (K Int) (EnumMapMap (K ID) Bool)@@ -209,29 +295,6 @@     size :: EnumMapMap k v -> Int     -- | Is the key present in the 'EnumMapMap'?     member :: k -> EnumMapMap k v -> Bool-    -- | An 'EnumMapMap' with one element-    ---    -- > singleton (5 :& K 3) "a" == fromList [(5 :& K 3, "a")]-    singleton :: k -> v -> EnumMapMap k v-    -- | Lookup up the value at a key in the 'EnumMapMap'.-    ---    -- > emm = fromList [(3 :& K 1, "a")]-    -- > lookup (3 :& K 1) emm == Just "a"-    -- > lookup (2 :& K 1) emm == Nothing-    ---    lookup :: k -> EnumMapMap k v -> Maybe v-    -- | Insert a new key\/value pair into the 'EnumMapMap'.-    insert :: k -> v -> EnumMapMap k v -> EnumMapMap k v-    -- | Insert with a combining function.-    insertWith :: (v -> v -> v)-                  -> k -> v -> EnumMapMap k v -> EnumMapMap k v-    insertWith f = insertWithKey (\_ -> f)-    -- | Insert with a combining function.-    insertWithKey :: (k -> v -> v -> v)-                  -> k -> v -> EnumMapMap k v -> EnumMapMap k v-    -- | Remove a key and it's value from the 'EnumMapMap'.  If the key is not-    -- present the original 'EnumMapMap' is returned.-    delete :: k -> EnumMapMap k v -> EnumMapMap k v     -- | The expression (@'alter' f k emm@) alters the value at @k@, or absence thereof.     -- 'alter' can be used to insert, delete, or update a value in an 'EnumMapMap'.     alter :: (Maybe v -> Maybe v) -> k -> EnumMapMap k v -> EnumMapMap k v@@ -247,11 +310,21 @@     -- binary operator.     foldrWithKey :: (k -> v -> t -> t) -> t -> EnumMapMap k v -> t     -- |  Convert the 'EnumMapMap' to a list of key\/value pairs.-    toList :: EnumMapMap k v -> [(k, v)]+    toList :: SubKey k k v =>+              EnumMapMap k v -> [(k, v)]     toList = foldrWithKey (\k x xs -> (k, x):xs) []     -- | Create a 'EnumMapMap' from a list of key\/value pairs.-    fromList :: [(k, v)] -> EnumMapMap k v+    fromList :: (SubKey k k v, Result k k v ~ v) => [(k, v)] -> EnumMapMap k v     fromList = foldlStrict (\t (k, x) -> insert k x t) empty+    -- | List of elements in ascending order of keys+    elems :: EnumMapMap k v -> [v]+    elems = foldr (:) []+    -- | List of keys+    keys :: EnumMapMap k v -> [k]+    keys = foldrWithKey (\k _ ks -> k:ks) []+    -- | The 'Data.EnumMapSet' of the keys.  'EnumMapMap' keys can be converted into+    -- 'Data.EnumMapSet' keys using 'toS', and back again using 'toK'.+    keysSet :: (HasSKey k) => EnumMapMap k v -> EnumMapMap (Skey k) ()     -- | The (left-biased) union of two 'EnumMapMap's.     -- It prefers the first 'EnumMapMap' when duplicate keys are encountered.     union :: EnumMapMap k v -> EnumMapMap k v -> EnumMapMap k v@@ -297,8 +370,7 @@     equal ::  Eq v => EnumMapMap k v -> EnumMapMap k v -> Bool     nequal :: Eq v => EnumMapMap k v -> EnumMapMap k v -> Bool --instance (Enum k, IsEmm t) => IsEmm (k :& t) where+instance (Eq k, Enum k, IsKey t, HasSKey t) => IsKey (k :& t) where     data EnumMapMap (k :& t) v = KCC (EMM k (EnumMapMap t v))      emptySubTrees e@(KCC emm) =@@ -346,30 +418,6 @@                    Nil         -> False           key = fromEnum key' -    singleton (key :& nxt) = KCC . Tip (fromEnum key) . singleton nxt--    lookup (key :& nxt) (KCC emm) = go emm-        where-          go (Bin _ m l r)-              | zero (fromEnum key) m = go l-              | otherwise = go r-          go (Tip kx x)-             = case kx == (fromEnum key) of-                 True -> lookup nxt x-                 False -> Nothing-          go Nil = Nothing--    insert (key :& nxt) val (KCC emm)-        = KCC $ insertWith_ (insert nxt val) key (singleton nxt val) emm--    insertWithKey f k@(key :& nxt) val (KCC emm) =-        KCC $ insertWith_ go key (singleton nxt val) emm-            where-              go = insertWithKey (\_ -> f k) nxt val--    delete !(key :& nxt) (KCC emm) =-        KCC $ alter_ (delete nxt) (fromEnum key) emm-     alter f !(key :& nxt) (KCC emm) =         KCC $ alter_ (alter f nxt) (fromEnum key) emm @@ -383,6 +431,8 @@         where           go k val z = foldrWithKey (\nxt -> f $ k :& nxt) z val +    keysSet (KCC emm) = KCC $ mapWithKey_ (\_ -> keysSet) emm+     union (KCC emm1) (KCC emm2) = KCC $ mergeWithKey' binD go id id emm1 emm2         where           go = \(Tip k1 x1) (Tip _ x2) -> tip k1 $ union x1 x2@@ -391,7 +441,7 @@             where               go = \(Tip k1 x1) (Tip _ x2) ->                    Tip k1 $ unionWithKey (g k1) x1 x2-              g k1 nxt = f $ (toEnum k1) :& nxt+              g k1 nxt = f $ toEnum k1 :& nxt      difference (KCC emm1) (KCC emm2) =         KCC $ mergeWithKey' binD go id (const Nil) emm1 emm2@@ -403,7 +453,7 @@             where               go = \(Tip k1 x1) (Tip _ x2) ->                    tip k1 $ differenceWithKey (\nxt ->-                                              f $ (toEnum k1) :& nxt) x1 x2+                                              f $ toEnum k1 :& nxt) x1 x2      intersection (KCC emm1) (KCC emm2) =         KCC $ mergeWithKey' binD go (const Nil) (const Nil) emm1 emm2@@ -415,7 +465,7 @@             where               go = \(Tip k1 x1) (Tip _ x2) ->                    tip k1 $ intersectionWithKey (\nxt ->-                                                f $ (toEnum k1) :& nxt) x1 x2+                                                f $ toEnum k1 :& nxt) x1 x2      equal (KCC emm1) (KCC emm2) = emm1 == emm2     nequal (KCC emm1) (KCC emm2) = emm1 /= emm2@@ -443,7 +493,7 @@ -- | 'alter_' is used to walk down the tree to find the 'EnumMapMap' to actually -- change.  If the new 'EnumMapMap' is null then it's removed from the containing -- 'EMM'.-alter_ :: (IsEmm b) =>+alter_ :: (IsKey b) =>           (EnumMapMap b v -> EnumMapMap b v)        -> Key        -> EMM a (EnumMapMap b v)@@ -501,7 +551,7 @@                | zero p1 m2        = bin' p2 m2 (go t1 l2) (g2 r2)                | otherwise         = bin' p2 m2 (g2 l2) (go t1 r2) -    go t1'@(Bin _ _ _ _) t2'@(Tip k2' _) = merge t2' k2' t1'+    go t1'@(Bin {}) t2'@(Tip k2' _) = merge t2' k2' t1'       where merge t2 k2 t1@(Bin p1 m1 l1 r1)                 | nomatch k2 p1 m1 = maybe_join p1 (g1 t1) k2 (g2 t2)                 | zero k2 m1 = bin' p1 m1 (merge t2 k2 l1) (g1 r1)@@ -511,7 +561,7 @@                 | otherwise = maybe_join k1 (g1 t1) k2 (g2 t2)             merge t2 _  Nil = g2 t2 -    go t1@(Bin _ _ _ _) Nil = g1 t1+    go t1@(Bin {}) Nil = g1 t1      go t1'@(Tip k1' _) t2' = merge t1' k1' t2'       where merge t1 k1 t2@(Bin p2 m2 l2 r2)@@ -538,7 +588,7 @@  -- Eq -instance (Eq v, IsEmm k) => Eq (EnumMapMap k v) where+instance (Eq v, IsKey k) => Eq (EnumMapMap k v) where   t1 == t2  = equal t1 t2   t1 /= t2  = nequal t1 t2 @@ -548,7 +598,7 @@  equalE :: Eq v => EMM k v -> EMM k v -> Bool equalE (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)-  = (m1 == m2) && (p1 == p2) && (equalE l1 l2) && (equalE r1 r2)+  = (m1 == m2) && (p1 == p2) && equalE l1 l2 && equalE r1 r2 equalE (Tip kx x) (Tip ky y)   = (kx == ky) && (x==y) equalE Nil Nil = True@@ -556,17 +606,17 @@  nequalE :: Eq v => EMM k v -> EMM k v -> Bool nequalE (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)-  = (m1 /= m2) || (p1 /= p2) || (nequalE l1 l2) || (nequalE r1 r2)+  = (m1 /= m2) || (p1 /= p2) || nequalE l1 l2 || nequalE r1 r2 nequalE (Tip kx x) (Tip ky y)   = (kx /= ky) || (x/=y) nequalE Nil Nil = False nequalE _   _   = True -instance (IsEmm k) => Functor (EnumMapMap k)+instance (IsKey k) => Functor (EnumMapMap k)     where       fmap = map -instance (IsEmm k) => Monoid (EnumMapMap k v) where+instance (IsKey k) => Monoid (EnumMapMap k v) where     mempty = empty     mappend = union     mconcat = unions@@ -610,7 +660,7 @@     p = mask p1 m {-# INLINE join #-} -joinD :: (IsEmm b) =>+joinD :: (IsKey b) =>          Prefix -> EMM a (EnumMapMap b v)       -> Prefix -> EMM a (EnumMapMap b v)       -> EMM a (EnumMapMap b v)@@ -634,7 +684,7 @@ {--------------------------------------------------------------------   @binD@ assures that we never have empty trees in the next level --------------------------------------------------------------------}-binD :: (IsEmm b) =>+binD :: (IsKey b) =>         Prefix -> Mask      -> EMM a (EnumMapMap b v)      -> EMM a (EnumMapMap b v)@@ -650,7 +700,7 @@ binD p m l r = Bin p m l r {-# INLINE binD #-} -tip :: (IsEmm b) => Key -> EnumMapMap b v -> EMM a (EnumMapMap b v)+tip :: (IsKey b) => Key -> EnumMapMap b v -> EMM a (EnumMapMap b v) tip k val     | null val  = Nil     | otherwise = Tip k val@@ -661,16 +711,16 @@ --------------------------------------------------------------------} zero :: Key -> Mask -> Bool zero i m-  = (natFromInt i) .&. (natFromInt m) == 0+  = natFromInt i .&. natFromInt m == 0 {-# INLINE zero #-}  nomatch,match :: Key -> Prefix -> Mask -> Bool nomatch i p m-  = (mask i m) /= p+  = mask i m /= p {-# INLINE nomatch #-}  match i p m-  = (mask i m) == p+  = mask i m == p {-# INLINE match #-}  mask :: Key -> Mask -> Prefix@@ -688,7 +738,7 @@  shorter :: Mask -> Mask -> Bool shorter m1 m2-  = (natFromInt m1) > (natFromInt m2)+  = natFromInt m1 > natFromInt m2 {-# INLINE shorter #-}  branchMask :: Prefix -> Prefix -> Mask
Data/EnumMapMap/Lazy.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE CPP, MagicHash, TypeFamilies, TypeOperators, BangPatterns,-             FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE CPP, BangPatterns, FlexibleInstances, GeneralizedNewtypeDeriving,+  MagicHash, MultiParamTypeClasses, TypeFamilies, TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  -----------------------------------------------------------------------------@@ -9,10 +9,24 @@ --                (c) Andriy Palamarchuk 2008 --                (c) Matthew West 2012 -- License     :  BSD-style--- Maintainer  : -- Stability   :  experimental -- Portability :  Uses GHC extensions --+-- Lazy 'EnumMapMap'.  Based upon "Data.IntMap.Lazy", this version uses multi+-- dimensional keys and 'Enum' types instead of 'Int's.  Keys are built using+-- the ':&' operator and terminated with 'K'.  They are stored using 'Int's so 2+-- keys that 'Enum' to the same 'Int' value will overwrite each other.  The+-- intension is that the 'Enum' types will actually be @newtype 'Int'@s.+--+-- > newtype AppleID = AppleID Int+-- > newtype TreeID = TreeID Int+-- > type Orchard = EnumMapMap (TreeID :& K AppleID) Apple+-- > apple = lookup (TreeID 4 :& K AppleID 32) orchard+--+-- The 'K' type is different to that used in "Data.EnumMapMap.Strict" so only lazy+-- operations can be performed on a lazy 'EnumMapMap'.+--+-- The functions are lazy on values, but strict on keys. -----------------------------------------------------------------------------  module Data.EnumMapMap.Lazy (@@ -62,7 +76,12 @@             -- * Lists             toList,             fromList,+            keys,+            elems,+            keysSet,             -- * Split/Join Keys+            toK,+            toS,             splitKey,             joinKey,             unsafeJoinKey@@ -71,10 +90,20 @@ import           Prelude hiding (lookup,map,filter,foldr,foldl,null,init)  import           Control.DeepSeq (NFData(rnf))+import           Data.Bits  import           Data.EnumMapMap.Base+import qualified Data.EnumMapSet.Base as EMS -instance (Enum k) => IsEmm (K k) where+-- | Keys are terminated with the 'K' type+--+-- > singleKey :: K Int+-- > singleKey = K 5+--+newtype K k = K k+           deriving (Show, Eq)++instance (Enum k, Eq k) => IsKey (K k) where     data EnumMapMap (K k) v = KEC (EMM k v)      emptySubTrees e@(KEC emm) =@@ -114,56 +143,6 @@                    Nil         -> False           key = fromEnum key' -    singleton !(K key) = KEC . Tip (fromEnum key)--    lookup !(K key') (KEC emm) = go emm-        where-          go (Bin _ m l r)-              | zero key m = go l-              | otherwise = go r-          go (Tip kx x)-             = case kx == key of-                 True -> Just x-                 False -> Nothing-          go Nil = Nothing-          key = fromEnum key'--    insert !(K key') val (KEC emm) = KEC $ go emm-        where-          go t = case t of-                   Bin p m l r-                       | nomatch key p m -> join key (Tip key val) p t-                       | zero key m      -> Bin p m (go l) r-                       | otherwise       -> Bin p m l (go r)-                   Tip ky _-                       | key == ky       -> Tip key val-                       | otherwise       -> join key (Tip key val) ky t-                   Nil                   -> Tip key val-          key = fromEnum key'--    insertWithKey f k@(K key') val (KEC emm) = KEC $ go emm-        where go t = case t of-                     Bin p m l r-                         | nomatch key p m -> join key (Tip key val) p t-                         | zero key m      -> Bin p m (go l) r-                         | otherwise       -> Bin p m l (go r)-                     Tip ky y-                         | key == ky       -> Tip key (f k val y)-                         | otherwise       -> join key (Tip key val) ky t-                     Nil                   -> Tip key val-              key = fromEnum key'--    delete !(K key') (KEC emm) = KEC $ go emm-        where-          go t = case t of-                   Bin p m l r | nomatch key p m -> t-                               | zero key m      -> bin p m (go l) r-                               | otherwise       -> bin p m l (go r)-                   Tip ky _    | key == ky       -> Nil-                               | otherwise       -> t-                   Nil                           -> Nil-          key = fromEnum key'-     alter f !(K key') (KEC emm) = KEC $ go emm         where           go t = case t of@@ -196,6 +175,18 @@           go z' (Tip _ x)     = f x z'           go z' (Bin _ _ l r) = go (go z' r) l     foldrWithKey f init (KEC emm) = foldrWithKey_ (\k -> f $ K k) init emm+    keysSet (KEC emm) = EMS.KSC $ go emm+        where+          go Nil        = EMS.Nil+          go (Tip kx _) = EMS.Tip (EMS.prefixOf kx) (EMS.bitmapOf kx)+          go (Bin p m l r)+              | m .&. EMS.suffixBitMask == 0 = EMS.Bin p m (go l) (go r)+              | otherwise = EMS.Tip (p .&. EMS.prefixBitMask)+                            (computeBm (computeBm 0 l) r)+              where+                computeBm !acc (Bin _ _ l' r') = computeBm (computeBm acc l') r'+                computeBm !acc (Tip kx _)      = acc .|. EMS.bitmapOf kx+                computeBm !acc Nil             = acc      union (KEC emm1) (KEC emm2) = KEC $ mergeWithKey' Bin const id id emm1 emm2     unionWithKey f (KEC emm1) (KEC emm2) =@@ -239,6 +230,11 @@           go (Tip _ v)     = rnf v           go (Bin _ _ l r) = go l `seq` go r +instance HasSKey (K k) where+    type Skey (K k) = EMS.S k+    toS (K !k) = EMS.S k+    toK (EMS.S !k) = K k+ {---------------------------------------------------------------------  Split/Join Keys ---------------------------------------------------------------------}@@ -249,3 +245,68 @@     type Head (k :& t) Z = K k     type Tail (k :& t) Z = t     splitKey Z (KCC emm) = KEC $ emm++instance (Enum k1, k1 ~ k2) => SubKey (K k1) (k2 :& t2) v where+    type Result (K k1) (k2 :& t2) v = EnumMapMap t2 v+    singleton !(K key) = KCC . Tip (fromEnum key)+    lookup !(K key') (KCC emm) = lookup_ (fromEnum key') emm+    insert !(K key') val (KCC emm) = KCC $ insert_ (fromEnum key') val emm+    insertWithKey f !k@(K key') val (KCC emm) =+        KCC $ insertWK (f k) (fromEnum key') val emm+    delete !(K key') (KCC emm) = KCC $ delete_ (fromEnum key') emm++instance (Enum k) => SubKey (K k) (K k) v where+    type Result (K k) (K k) v = v+    singleton !(K key) = KEC . Tip (fromEnum key)+    lookup (K key') (KEC emm) = lookup_ (fromEnum key') emm+    insert !(K key') val (KEC emm) = KEC $ insert_ (fromEnum key') val emm+    insertWithKey f !k@(K key') val (KEC emm) =+        KEC $ insertWK (f k) (fromEnum key') val emm+    delete !(K key') (KEC emm) = KEC $ delete_ (fromEnum key') emm++lookup_ :: Key -> EMM k v -> Maybe v+lookup_ !key emm =+    case emm of+      Bin _ m l r+          | zero key m -> lookup_ key l+          | otherwise  -> lookup_ key r+      Tip kx x         -> if kx == key then Just x else Nothing+      Nil              -> Nothing++insert_ :: Key -> v -> EMM k v -> EMM k v+insert_ !key val = go+    where+      go emm =+          case emm of+            Bin p m l r+                | nomatch key p m -> join key (Tip key val) p emm+                | zero key m      -> Bin p m (go l) r+                | otherwise       -> Bin p m l (go r)+            Tip ky _+                | key == ky       -> Tip key val+                | otherwise       -> join key (Tip key val) ky emm+            Nil                   -> Tip key val++insertWK :: (v -> v -> v) -> Key -> v -> EMM k v -> EMM k v+insertWK f !key val = go+    where+      go emm =+          case emm of+            Bin p m l r+                | nomatch key p m -> join key (Tip key val) p emm+                | zero key m      -> Bin p m (go l) r+                | otherwise       -> Bin p m l (go r)+            Tip ky y+                | key == ky       -> Tip key (f val y)+                | otherwise       -> join key (Tip key val) ky emm+            Nil                   -> Tip key val++delete_ :: Key -> EMM k v -> EMM k v+delete_ !key emm =+    case emm of+      Bin p m l r | nomatch key p m -> emm+                  | zero key m      -> bin p m (delete_ key l) r+                  | otherwise       -> bin p m l (delete_ key r)+      Tip ky _    | key == ky       -> Nil+                  | otherwise       -> emm+      Nil                           -> Nil
Data/EnumMapMap/Strict.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE MagicHash, MultiParamTypeClasses, TypeFamilies, TypeOperators,-  BangPatterns, FlexibleInstances, FlexibleContexts, CPP #-}+{-# LANGUAGE CPP, BangPatterns, FlexibleInstances, GeneralizedNewtypeDeriving,+  MagicHash, MultiParamTypeClasses, TypeFamilies, TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  -----------------------------------------------------------------------------@@ -9,10 +9,24 @@ --                (c) Andriy Palamarchuk 2008 --                (c) Matthew West 2012 -- License     :  BSD-style--- Maintainer  : -- Stability   :  experimental -- Portability :  Uses GHC extensions --+-- Strict 'EnumMapMap'.  Based upon "Data.IntMap.Strict", this version uses multi+-- dimensional keys and 'Enum' types instead of 'Int's.  Keys are built using+-- the ':&' operator and terminated with 'K'.  They are stored using 'Int's so 2+-- keys that 'Enum' to the same 'Int' value will overwrite each other.  The+-- intension is that the 'Enum' types will actually be @newtype 'Int'@s.+--+-- > newtype AppleID = AppleID Int+-- > newtype TreeID = TreeID Int+-- > type Orchard = EnumMapMap (TreeID :& K AppleID) Apple+-- > apple = lookup (TreeID 4 :& K AppleID 32) orchard+--+-- The 'K' type is different to that used in "Data.EnumMapMap.Lazy" so only strict+-- operations can be performed on a strict 'EnumMapMap'.+--+-- The functions are strict on values and keys. -----------------------------------------------------------------------------  module Data.EnumMapMap.Strict (@@ -63,7 +77,12 @@             -- * Lists             toList,             fromList,+            keys,+            elems,+            keysSet,             -- * Split/Join Keys+            toK,+            toS,             splitKey,             joinKey,             unsafeJoinKey@@ -72,10 +91,20 @@ import           Prelude hiding (lookup,map,filter,foldr,foldl,null, init)  import           Control.DeepSeq (NFData(rnf))+import           Data.Bits  import           Data.EnumMapMap.Base+import qualified Data.EnumMapSet.Base as EMS -instance (Enum k) => IsEmm (K k) where+-- | Keys are terminated with the 'K' type+--+-- > singleKey :: K Int+-- > singleKey = K 5+--+newtype K k = K k+           deriving (Show, Eq)++instance (Enum k, Eq k) => IsKey (K k) where     data EnumMapMap (K k) v = KEC (EMM k v)      emptySubTrees e@(KEC emm) =@@ -115,56 +144,6 @@                    Nil         -> False           key = fromEnum key' -    singleton !(K key) !val = KEC $ Tip (fromEnum key) val--    lookup !(K key') (KEC emm) = go emm-        where-          go (Bin _ m l r)-              | zero key m = go l-              | otherwise = go r-          go (Tip kx x)-             = case kx == key of-                 True -> Just x-                 False -> Nothing-          go Nil = Nothing-          key = fromEnum key'--    insert !(K key') !val (KEC emm) = KEC $ go emm-        where-          go t = case t of-                   Bin p m l r-                       | nomatch key p m -> join key (Tip key val) p t-                       | zero key m      -> Bin p m (go l) r-                       | otherwise       -> Bin p m l (go r)-                   Tip ky _-                       | key == ky       -> Tip key val-                       | otherwise       -> join key (Tip key val) ky t-                   Nil                   -> Tip key val-          key = fromEnum key'--    insertWithKey f k@(K key') !val (KEC emm) = KEC $ go emm-        where go t = case t of-                     Bin p m l r-                         | nomatch key p m -> join key (Tip key val) p t-                         | zero key m      -> Bin p m (go l) r-                         | otherwise       -> Bin p m l (go r)-                     Tip ky y-                         | key == ky       -> Tip key $! (f k val y)-                         | otherwise       -> join key (Tip key val) ky t-                     Nil                   -> Tip key val-              key = fromEnum key'--    delete !(K key') (KEC emm) = KEC $ go emm-        where-          go t = case t of-                   Bin p m l r | nomatch key p m -> t-                               | zero key m      -> bin p m (go l) r-                               | otherwise       -> bin p m l (go r)-                   Tip ky _    | key == ky       -> Nil-                               | otherwise       -> t-                   Nil                           -> Nil-          key = fromEnum key'-     alter f !(K key') (KEC emm) = KEC $ go emm         where           go t = case t of@@ -197,6 +176,18 @@           go z' (Tip _ x)     = f x z'           go z' (Bin _ _ l r) = go (go z' r) l     foldrWithKey f init (KEC emm) = foldrWithKey_ (\k -> f $! K k) init emm+    keysSet (KEC emm) = EMS.KSC $ go emm+        where+          go Nil        = EMS.Nil+          go (Tip kx _) = EMS.Tip (EMS.prefixOf kx) (EMS.bitmapOf kx)+          go (Bin p m l r)+              | m .&. EMS.suffixBitMask == 0 = EMS.Bin p m (go l) (go r)+              | otherwise = EMS.Tip (p .&. EMS.prefixBitMask)+                            (computeBm (computeBm 0 l) r)+              where+                computeBm !acc (Bin _ _ l' r') = computeBm (computeBm acc l') r'+                computeBm !acc (Tip kx _)      = acc .|. EMS.bitmapOf kx+                computeBm !acc Nil             = acc      union (KEC emm1) (KEC emm2) = KEC $ mergeWithKey' Bin const id id emm1 emm2     unionWithKey f (KEC emm1) (KEC emm2) =@@ -240,6 +231,11 @@           go (Tip _ v)     = rnf v           go (Bin _ _ l r) = go l `seq` go r +instance HasSKey (K k) where+    type Skey (K k) = EMS.S k+    toS (K !k) = EMS.S k+    toK (EMS.S !k) = K k+ {---------------------------------------------------------------------  Split/Join Keys ---------------------------------------------------------------------}@@ -250,3 +246,68 @@     type Head (k :& t) Z = K k     type Tail (k :& t) Z = t     splitKey Z (KCC emm) = KEC $ emm++instance (Enum k1, k1 ~ k2) => SubKey (K k1) (k2 :& t2) v where+    type Result (K k1) (k2 :& t2) v = EnumMapMap t2 v+    singleton !(K key) = KCC . Tip (fromEnum key)+    lookup (K key') (KCC emm) = lookup_ (fromEnum key') emm+    insert !(K key') val (KCC emm) = KCC $ insert_ (fromEnum key') val emm+    insertWithKey f !k@(K key') val (KCC emm) =+        KCC $ insertWK (f k) (fromEnum key') val emm+    delete !(K key') (KCC emm) = KCC $ delete_ (fromEnum key') emm++instance (Enum k) => SubKey (K k) (K k) v where+    type Result (K k) (K k) v = v+    singleton !(K key) !val = KEC $! Tip (fromEnum key) val+    lookup (K key') (KEC emm) = lookup_ (fromEnum key') emm+    insert !(K key') !val (KEC emm) = KEC $ insert_ (fromEnum key') val emm+    insertWithKey f !k@(K key') !val (KEC emm) =+        KEC $ insertWK (f k) (fromEnum key') val emm+    delete !(K key') (KEC emm) = KEC $ delete_ (fromEnum key') emm++lookup_ :: Key -> EMM k v -> Maybe v+lookup_ !key emm =+    case emm of+      Bin _ m l r+          | zero key m -> lookup_ key l+          | otherwise  -> lookup_ key r+      Tip kx x         -> if kx == key then Just x else Nothing+      Nil              -> Nothing++insert_ :: Key -> v -> EMM k v -> EMM k v+insert_ !key val = go+    where+      go emm =+          case emm of+            Bin p m l r+                | nomatch key p m -> join key (Tip key val) p emm+                | zero key m      -> Bin p m (go l) r+                | otherwise       -> Bin p m l (go r)+            Tip ky _+                | key == ky       -> Tip key val+                | otherwise       -> join key (Tip key val) ky emm+            Nil                   -> Tip key val++insertWK :: (v -> v -> v) -> Key -> v -> EMM k v -> EMM k v+insertWK f !key val = go+    where+      go emm =+          case emm of+            Bin p m l r+                | nomatch key p m -> join key (Tip key val) p emm+                | zero key m      -> Bin p m (go l) r+                | otherwise       -> Bin p m l (go r)+            Tip ky y+                | key == ky       -> Tip key (f val y)+                | otherwise       -> join key (Tip key val) ky emm+            Nil                   -> Tip key val++delete_ :: Key -> EMM k v -> EMM k v+delete_ !key emm =+    case emm of+      Bin p m l r | nomatch key p m -> emm+                  | zero key m      -> bin p m (delete_ key l) r+                  | otherwise       -> bin p m l (delete_ key r)+      Tip ky _    | key == ky       -> Nil+                  | otherwise       -> emm+      Nil                           -> Nil
Data/EnumMapSet.hs view
@@ -1,28 +1,37 @@-{-# LANGUAGE BangPatterns, CPP, MagicHash, TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE TypeFamilies #-}  ----------------------------------------------------------------------------- -- | -- Module      :  Data.EnumMapSet -- Copyright   :  (c) Daan Leijen 2002---                (c) Andriy Palamarchuk 2008+--                (c) Joachim Breitner 2011 --                (c) Matthew West 2012 -- License     :  BSD-style--- Maintainer  : -- Stability   :  experimental -- Portability :  Uses GHC extensions ----- Based on Data.IntSet.+-- Based on "Data.IntSet", this module provides multi-dimensional sets of+-- 'Enums'. Keys are built using ':&' and terminated with 'S'.  They are stored+-- using 'Int's so 2 keys that 'Enum' to the same 'Int' value will overwrite+-- each other.  The intension is that the 'Enum' types will actually be @newtype+-- 'Int'@s. --+--+-- > newtype AppleID = AppleID Int+-- > newtype TreeID = TreeID Int+-- > type Orchard = EnumMapSet (TreeID :& S AppleID)+-- > applePresent = member (TreeID 4 :& K AppleID 32) orchard+-- -----------------------------------------------------------------------------  module Data.EnumMapSet (             EnumMapSet,-            K(..), (:&)(..),+            S(..), (:&)(..),             -- * Query-            null,+            EMS.null,             size,             member,+            EMS.lookup,             -- * Construction             empty,             singleton,@@ -33,417 +42,13 @@             difference,             intersection,             -- * Map-            map,+            EMS.map,             -- * Folds-            foldr,+            EMS.foldr,             -- * Lists             toList,-            fromList+            fromList,+            keys ) where -import           Prelude hiding (lookup,-                                 map,-                                 filter,-                                 foldr, foldl,-                                 null, init,-                                 head, tail)--import           Data.Bits-import qualified Data.List as List-import           GHC.Exts (Word(..), Int(..))-import           GHC.Prim (indexInt8OffAddr#)-#include "MachDeps.h"--import           Data.EnumMapMap.Base ((:&)(..), K(..), EMM(..),-                                       IsEmm,-                                       EnumMapMap,-                                       Prefix, Nat,-                                       intFromNat, bin,-                                       shiftRL, shiftLL,-                                       nomatch, zero,-                                       join, shorter,-                                       foldlStrict)-import qualified Data.EnumMapMap.Base as EMM--type EnumMapSet k = EnumMapMap k ()--type BitMap = Word--instance (Enum k) => IsEmm (K k) where-    data EnumMapMap (K k) v = KSC (EMM k BitMap)--    emptySubTrees e@(KSC emm) =-        case emm of-          Nil -> False-          _   -> EMM.emptySubTrees_ e-    emptySubTrees_ (KSC emm) = go emm-        where-          go t = case t of-                   Bin _ _ l r -> go l || go r-                   Tip _ _     -> False-                   Nil         -> True--    removeEmpties = id--    unsafeJoinKey (KSC _) = undefined--    empty = KSC Nil--    null (KSC ems) = case ems of-                       Nil -> True-                       _   -> False--    size (KSC ems) = go ems-        where-          go (Bin _ _ l r) = go l + go r-          go (Tip _ bm)    = bitcount 0 bm-          go Nil           = 0--    member !(K key') (KSC ems) = key `seq` go ems-        where-          go (Bin p m l r)-              | nomatch key p m = False-              | zero key m      = go l-              | otherwise       = go r-          go (Tip y bm) = prefixOf key == y && bitmapOf key .&. bm /= 0-          go Nil = False-          key = fromEnum key'--    singleton (K key') _-        = key `seq` KSC $ Tip (prefixOf key) (bitmapOf key)-          where key = fromEnum key'--    insert (K key') _ (KSC ems)-        = key `seq` KSC $ insertBM (prefixOf key) (bitmapOf key) ems-          where key = fromEnum key'--    delete (K key') (KSC ems)-        = key `seq` KSC $ deleteBM (prefixOf key) (bitmapOf key) ems-          where key = fromEnum key'--    foldrWithKey f init (KSC ems)-        = case ems of Bin _ m l r | m < 0 -> go (go init l) r-                                  | otherwise -> go (go init r) l-                      _          -> go init ems-          where-            go init' Nil           = init'-            go init' (Tip kx bm)   = foldrBits kx f' init' bm-            go init' (Bin _ _ l r) = go (go init' r) l-            f' !k t = f (K $ toEnum k) undefined t--    union (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2-        where-          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)-              | shorter m1 m2  = union1-              | shorter m2 m1  = union2-              | p1 == p2       = Bin p1 m1 (go l1 l2) (go r1 r2)-              | otherwise      = join p1 t1 p2 t2-              where-                union1  | nomatch p2 p1 m1  = join p1 t1 p2 t2-                        | zero p2 m1        = Bin p1 m1 (go l1 t2) r1-                        | otherwise         = Bin p1 m1 l1 (go r1 t2)--                union2  | nomatch p1 p2 m2  = join p1 t1 p2 t2-                        | zero p1 m2        = Bin p2 m2 (go t1 l2) r2-                        | otherwise         = Bin p2 m2 l2 (go t1 r2)--          go t@(Bin _ _ _ _) (Tip kx bm) = insertBM kx bm t-          go t@(Bin _ _ _ _) Nil = t-          go (Tip kx bm) t = insertBM kx bm t-          go Nil t = t--    difference (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2-        where-          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)-              | shorter m1 m2  = difference1-              | shorter m2 m1  = difference2-              | p1 == p2       = bin p1 m1 (go l1 l2) (go r1 r2)-              | otherwise      = t1-              where-                difference1 | nomatch p2 p1 m1  = t1-                            | zero p2 m1        = bin p1 m1 (go l1 t2) r1-                            | otherwise         = bin p1 m1 l1 (go r1 t2)--                difference2 | nomatch p1 p2 m2  = t1-                            | zero p1 m2        = go t1 l2-                            | otherwise         = go t1 r2--          go t@(Bin _ _ _ _) (Tip kx bm) = deleteBM kx bm t-          go t@(Bin _ _ _ _) Nil = t--          go t1@(Tip kx bm) t2 = differenceTip t2-              where differenceTip (Bin p2 m2 l2 r2)-                        | nomatch kx p2 m2 = t1-                        | zero kx m2 = differenceTip l2-                        | otherwise = differenceTip r2-                    differenceTip (Tip kx2 bm2)-                        | kx == kx2 = tip kx (bm .&. complement bm2)-                        | otherwise = t1-                    differenceTip Nil = t1--          go Nil _ = Nil--    intersection (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2-        where-          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)-              | shorter m1 m2  = intersection1-              | shorter m2 m1  = intersection2-              | p1 == p2       = bin p1 m1 (go l1 l2) (go r1 r2)-              | otherwise      = Nil-              where-                intersection1 | nomatch p2 p1 m1  = Nil-                              | zero p2 m1        = go l1 t2-                              | otherwise         = go r1 t2--                intersection2 | nomatch p1 p2 m2  = Nil-                              | zero p1 m2        = go t1 l2-                              | otherwise         = go t1 r2--          go t1@(Bin _ _ _ _) (Tip kx2 bm2) = intersectBM t1-              where intersectBM (Bin p1 m1 l1 r1)-                        | nomatch kx2 p1 m1 = Nil-                        | zero kx2 m1       = intersectBM l1-                        | otherwise         = intersectBM r1-                    intersectBM (Tip kx1 bm1)-                        | kx1 == kx2 = tip kx1 (bm1 .&. bm2)-                        | otherwise = Nil-                    intersectBM Nil = Nil--          go (Bin _ _ _ _) Nil = Nil--          go (Tip kx1 bm1) t2 = intersectBM t2-              where intersectBM (Bin p2 m2 l2 r2)-                        | nomatch kx1 p2 m2 = Nil-                        | zero kx1 m2       = intersectBM l2-                        | otherwise         = intersectBM r2-                    intersectBM (Tip kx2 bm2)-                        | kx1 == kx2 = tip kx1 (bm1 .&. bm2)-                        | otherwise = Nil-                    intersectBM Nil = Nil--          go Nil _ = Nil--    equal (KSC ems1) (KSC ems2) = go ems1 ems2-        where-          go (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)-              = (m1 == m2) && (p1 == p2) && (go l1 l2) && (go r1 r2)-          go (Tip kx1 bm1) (Tip kx2 bm2)-              = kx1 == kx2 && bm1 == bm2-          go Nil Nil = True-          go _   _   = False--    nequal (KSC ems1) (KSC ems2) = go ems1 ems2-        where-          go (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)-              = (m1 /= m2) || (p1 /= p2) || (go l1 l2) || (go r1 r2)-          go (Tip kx1 bm1) (Tip kx2 bm2)-              = kx1 /= kx2 || bm1 /= bm2-          go Nil Nil = False-          go _   _   = True--    insertWith = undefined-    insertWithKey = undefined-    lookup = undefined-    alter = undefined-    foldr = undefined-    map = undefined-    mapWithKey = undefined-    unionWith = undefined-    unionWithKey = undefined-    differenceWith = undefined-    differenceWithKey = undefined-    intersectionWith = undefined-    intersectionWithKey = undefined-    fromList = undefined-    toList = undefined--{----------------------------------------------------------------------  Exported API--  The Set API is somewhat different to the Map API so we define the following-  functions to call the IsEMM functions with the type of 'v' as (), hoping that-  GHC will inline away all the empty parameters.----------------------------------------------------------------------}--null :: (IsEmm k) => EnumMapSet k -> Bool-null = EMM.null--size :: (IsEmm k) => EnumMapSet k -> Int-size = EMM.size--member ::(IsEmm k) => k -> EnumMapSet k -> Bool-member = EMM.member--empty :: (IsEmm k) => EnumMapSet k-empty = EMM.empty--singleton :: (IsEmm k) => k -> EnumMapSet k-singleton !key = EMM.singleton key ()--insert :: (IsEmm k) => k -> EnumMapSet k -> EnumMapSet k-insert !key = EMM.insert key ()--delete :: (IsEmm k) => k -> EnumMapSet k -> EnumMapSet k-delete = EMM.delete---- This function has not been optimised in any way.-foldr :: (IsEmm k) => (k -> t -> t) -> t -> EnumMapSet k -> t-foldr f = EMM.foldrWithKey go-    where-      go k _ z = f k z---- | @'map' f s@ is the set obtained by applying @f@ to each element of @s@.------ It's worth noting that the size of the result may be smaller if,--- for some @(x,y)@, @x \/= y && f x == f y@-map :: (IsEmm k1, IsEmm k2) =>-       (k1 -> k2) -> EnumMapSet k1 -> EnumMapSet k2-map f = fromList . List.map f . toList--union :: (IsEmm k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k-union = EMM.union--difference :: (IsEmm k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k-difference = EMM.difference--intersection :: (IsEmm k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k-intersection = EMM.intersection--{----------------------------------------------------------------------  List----------------------------------------------------------------------}--fromList :: IsEmm k => [k] -> EnumMapSet k-fromList xs-    = foldlStrict (\t x -> insert x t) empty xs--toList :: IsEmm k => EnumMapSet k -> [k]-toList = foldr (:) []--{----------------------------------------------------------------------  Instances----------------------------------------------------------------------}--{----------------------------------------------------------------------  Helper functions----------------------------------------------------------------------}--insertBM :: Prefix -> BitMap -> EMM k BitMap -> EMM k BitMap-insertBM !kx !bm t-    = case t of-    Bin p m l r-      | nomatch kx p m -> join kx (Tip kx bm) p t-      | zero kx m      -> Bin p m (insertBM kx bm l) r-      | otherwise      -> Bin p m l (insertBM kx bm r)-    Tip kx' bm'-      | kx' == kx -> Tip kx' (bm .|. bm')-      | otherwise -> join kx (Tip kx bm) kx' t-    Nil -> Tip kx bm--deleteBM :: Prefix -> BitMap -> EMM k BitMap -> EMM k BitMap-deleteBM !kx !bm t-  = case t of-      Bin p m l r-          | nomatch kx p m -> t-          | zero kx m      -> bin p m (deleteBM kx bm l) r-          | otherwise      -> bin p m l (deleteBM kx bm r)-      Tip kx' bm'-          | kx' == kx -> tip kx (bm' .&. complement bm)-          | otherwise -> t-      Nil -> Nil--{---------------------------------------------------------------------  @tip@ assures that we never have empty bitmaps within a tree.---------------------------------------------------------------------}-tip :: Prefix -> BitMap -> EMM k BitMap-tip _ 0 = Nil-tip kx bm = Tip kx bm-{-# INLINE tip #-}--{-----------------------------------------------------------------------  Functions that generate Prefix and BitMap of a Key or a Suffix.--  Commentary and credits can be found with the original code in-  Data/IntSet/Base.hs in 'containers 5.0'.-----------------------------------------------------------------------}--suffixBitMask :: Int-suffixBitMask = bitSize (undefined::Word) - 1-{-# INLINE suffixBitMask #-}--prefixBitMask :: Int-prefixBitMask = complement suffixBitMask-{-# INLINE prefixBitMask #-}--prefixOf :: Int -> Prefix-prefixOf x = x .&. prefixBitMask-{-# INLINE prefixOf #-}--suffixOf :: Int -> Int-suffixOf x = x .&. suffixBitMask-{-# INLINE suffixOf #-}--bitmapOfSuffix :: Int -> BitMap-bitmapOfSuffix s = 1 `shiftLL` s-{-# INLINE bitmapOfSuffix #-}--bitmapOf :: Int -> BitMap-bitmapOf x = bitmapOfSuffix (suffixOf x)-{-# INLINE bitmapOf #-}--bitcount :: Int -> Word -> Int-bitcount a0 x0 = go a0 x0-  where go a 0 = a-        go a x = go (a + 1) (x .&. (x-1))-{-# INLINE bitcount #-}--{-----------------------------------------------------------------------  Folds over a BitMap.--  Commentary and credits can be found with the original code in-  Data/IntSet/Base.hs in 'containers 5.0'.-----------------------------------------------------------------------}--foldrBits :: Int -> (Int -> a -> a) -> a -> Nat -> a--{-# INLINE foldrBits #-}--indexOfTheOnlyBit :: Nat -> Int-{-# INLINE indexOfTheOnlyBit #-}-indexOfTheOnlyBit bitmask =-  I# (lsbArray `indexInt8OffAddr#` unboxInt-                   (intFromNat ((bitmask * magic) `shiftRL` offset)))-  where unboxInt (I# i) = i-#if WORD_SIZE_IN_BITS==32-        magic = 0x077CB531-        offset = 27-        !lsbArray = "\0\1\28\2\29\14\24\3\30\22\20\15\25\17\4\8\31\27\13\23\21\19\16\7\26\12\18\6\11\5\10\9"#-#else-        magic = 0x07EDD5E59A4E28C2-        offset = 58-        !lsbArray = "\63\0\58\1\59\47\53\2\60\39\48\27\54\33\42\3\61\51\37\40\49\18\28\20\55\30\34\11\43\14\22\4\62\57\46\52\38\26\32\41\50\36\17\19\29\10\13\21\56\45\25\31\35\16\9\12\44\24\15\8\23\7\6\5"#-#endif-lowestBitMask :: Nat -> Nat-lowestBitMask x = x .&. negate x-{-# INLINE lowestBitMask #-}--revNat :: Nat -> Nat-#if WORD_SIZE_IN_BITS==32-revNat x1 = case ((x1 `shiftRL` 1) .&. 0x55555555) .|. ((x1 .&. 0x55555555) `shiftLL` 1) of-              x2 -> case ((x2 `shiftRL` 2) .&. 0x33333333) .|. ((x2 .&. 0x33333333) `shiftLL` 2) of-                 x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F) `shiftLL` 4) of-                   x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF) .|. ((x4 .&. 0x00FF00FF) `shiftLL` 8) of-                     x5 -> ( x5 `shiftRL` 16             ) .|. ( x5               `shiftLL` 16);-#else-revNat x1 = case ((x1 `shiftRL` 1) .&. 0x5555555555555555) .|. ((x1 .&. 0x5555555555555555) `shiftLL` 1) of-              x2 -> case ((x2 `shiftRL` 2) .&. 0x3333333333333333) .|. ((x2 .&. 0x3333333333333333) `shiftLL` 2) of-                 x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F0F0F0F0F) `shiftLL` 4) of-                   x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF00FF00FF) .|. ((x4 .&. 0x00FF00FF00FF00FF) `shiftLL` 8) of-                     x5 -> case ((x5 `shiftRL` 16) .&. 0x0000FFFF0000FFFF) .|. ((x5 .&. 0x0000FFFF0000FFFF) `shiftLL` 16) of-                       x6 -> ( x6 `shiftRL` 32             ) .|. ( x6               `shiftLL` 32);-#endif-foldrBits prefix f z bitmap = go (revNat bitmap) z-  where go bm acc | bm == 0 = acc-                  | otherwise = case lowestBitMask bm of-                                  bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of-                                    bi -> bi `seq` go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS-1)-bi)) acc)+import Data.EnumMapSet.Base as EMS
+ Data/EnumMapSet/Base.hs view
@@ -0,0 +1,565 @@+{-# LANGUAGE BangPatterns, CPP, FlexibleContexts, FlexibleInstances,+ GeneralizedNewtypeDeriving, MagicHash, MultiParamTypeClasses, TypeFamilies,+ TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Data.EnumMapSet+-- Copyright   :  (c) Daan Leijen 2002+--                (c) Joachim Breitner 2011+--                (c) Matthew West 2012+-- License     :  BSD-style+-- Stability   :  experimental+-- Portability :  Uses GHC extensions+--+-- Based on Data.IntSet.Base+--+-----------------------------------------------------------------------------++module Data.EnumMapSet.Base (+            EnumMapSet,+            S(..), (:&)(..),+            -- * Query+            null,+            size,+            member,+            lookup,+            -- * Construction+            empty,+            singleton,+            insert,+            insertSub,+            delete,+            -- * Combine+            union,+            difference,+            intersection,+            -- * Map+            map,+            -- * Folds+            foldr,+            -- * Lists+            toList,+            fromList,+            keys,+            -- * Internals+            EMS(..),+            EnumMapMap(KSC),+            suffixBitMask,+            prefixBitMask,+            bitmapOf,+            prefixOf+) where++import           Prelude hiding (lookup,+                                 map,+                                 filter,+                                 foldr, foldl,+                                 null, init,+                                 head, tail)++import           Data.Bits+import qualified Data.List as List+import           GHC.Exts (Word(..), Int(..))+import           GHC.Prim (indexInt8OffAddr#)+#include "MachDeps.h"++import           Data.EnumMapMap.Base ((:&)(..),+                                       IsKey,+                                       EnumMapMap,+                                       Prefix, Nat, Mask,+                                       branchMask, mask,+                                       intFromNat,+                                       shiftRL, shiftLL,+                                       nomatch, zero,+                                       shorter,+                                       foldlStrict)+import qualified Data.EnumMapMap.Base as EMM++type EnumMapSet k = EnumMapMap k ()++type BitMap = Word++-- | Keys are terminated with the 'S' type.+--+-- > singleKey :: S Int+-- > singleKey = S 5+--+newtype S k = S k+           deriving (Show, Eq)++-- This is used instead of @EMM k BitMap@ in order to unpack the 'BitMap' in+-- 'Tip'. Hopefully this will lead to much optimisation by GHC.+data EMS k = Bin {-# UNPACK #-} !Prefix {-# UNPACK #-} !Mask+                 !(EMS k) !(EMS k)+           | Tip {-# UNPACK #-} !Int {-# UNPACK #-} !BitMap+           | Nil+             deriving (Show)++instance (Enum k, Eq k) => IsKey (S k) where+    data EnumMapMap (S k) v = KSC (EMS k)++    emptySubTrees e@(KSC emm) =+        case emm of+          Nil -> False+          _   -> EMM.emptySubTrees_ e+    emptySubTrees_ (KSC emm) = go emm+        where+          go t = case t of+                   Bin _ _ l r -> go l || go r+                   Tip _ _     -> False+                   Nil         -> True++    removeEmpties = id++    unsafeJoinKey (KSC _) = undefined++    empty = KSC Nil++    null (KSC ems) = case ems of+                       Nil -> True+                       _   -> False++    size (KSC ems) = go ems+        where+          go (Bin _ _ l r) = go l + go r+          go (Tip _ bm)    = bitcount 0 bm+          go Nil           = 0++    member !(S key') (KSC ems) = key `seq` go ems+        where+          go (Bin p m l r)+              | nomatch key p m = False+              | zero key m      = go l+              | otherwise       = go r+          go (Tip y bm) = prefixOf key == y && bitmapOf key .&. bm /= 0+          go Nil = False+          key = fromEnum key'++    foldrWithKey f init (KSC ems)+        = case ems of Bin _ m l r | m < 0 -> go (go init l) r+                                  | otherwise -> go (go init r) l+                      _          -> go init ems+          where+            go init' Nil           = init'+            go init' (Tip kx bm)   = foldrBits kx f' init' bm+            go init' (Bin _ _ l r) = go (go init' r) l+            f' !k t = f (S $ toEnum k) undefined t++    union (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2+        where+          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)+              | shorter m1 m2  = union1+              | shorter m2 m1  = union2+              | p1 == p2       = Bin p1 m1 (go l1 l2) (go r1 r2)+              | otherwise      = join p1 t1 p2 t2+              where+                union1  | nomatch p2 p1 m1  = join p1 t1 p2 t2+                        | zero p2 m1        = Bin p1 m1 (go l1 t2) r1+                        | otherwise         = Bin p1 m1 l1 (go r1 t2)++                union2  | nomatch p1 p2 m2  = join p1 t1 p2 t2+                        | zero p1 m2        = Bin p2 m2 (go t1 l2) r2+                        | otherwise         = Bin p2 m2 l2 (go t1 r2)++          go t@(Bin _ _ _ _) (Tip kx bm) = insertBM kx bm t+          go t@(Bin _ _ _ _) Nil = t+          go (Tip kx bm) t = insertBM kx bm t+          go Nil t = t++    difference (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2+        where+          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)+              | shorter m1 m2  = difference1+              | shorter m2 m1  = difference2+              | p1 == p2       = bin p1 m1 (go l1 l2) (go r1 r2)+              | otherwise      = t1+              where+                difference1 | nomatch p2 p1 m1  = t1+                            | zero p2 m1        = bin p1 m1 (go l1 t2) r1+                            | otherwise         = bin p1 m1 l1 (go r1 t2)++                difference2 | nomatch p1 p2 m2  = t1+                            | zero p1 m2        = go t1 l2+                            | otherwise         = go t1 r2++          go t@(Bin _ _ _ _) (Tip kx bm) = deleteBM kx bm t+          go t@(Bin _ _ _ _) Nil = t++          go t1@(Tip kx bm) t2 = differenceTip t2+              where differenceTip (Bin p2 m2 l2 r2)+                        | nomatch kx p2 m2 = t1+                        | zero kx m2 = differenceTip l2+                        | otherwise = differenceTip r2+                    differenceTip (Tip kx2 bm2)+                        | kx == kx2 = tip kx (bm .&. complement bm2)+                        | otherwise = t1+                    differenceTip Nil = t1++          go Nil _ = Nil++    intersection (KSC ems1) (KSC ems2) = KSC $ go ems1 ems2+        where+          go t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)+              | shorter m1 m2  = intersection1+              | shorter m2 m1  = intersection2+              | p1 == p2       = bin p1 m1 (go l1 l2) (go r1 r2)+              | otherwise      = Nil+              where+                intersection1 | nomatch p2 p1 m1  = Nil+                              | zero p2 m1        = go l1 t2+                              | otherwise         = go r1 t2++                intersection2 | nomatch p1 p2 m2  = Nil+                              | zero p1 m2        = go t1 l2+                              | otherwise         = go t1 r2++          go t1@(Bin _ _ _ _) (Tip kx2 bm2) = intersectBM t1+              where intersectBM (Bin p1 m1 l1 r1)+                        | nomatch kx2 p1 m1 = Nil+                        | zero kx2 m1       = intersectBM l1+                        | otherwise         = intersectBM r1+                    intersectBM (Tip kx1 bm1)+                        | kx1 == kx2 = tip kx1 (bm1 .&. bm2)+                        | otherwise = Nil+                    intersectBM Nil = Nil++          go (Bin _ _ _ _) Nil = Nil++          go (Tip kx1 bm1) t2 = intersectBM t2+              where intersectBM (Bin p2 m2 l2 r2)+                        | nomatch kx1 p2 m2 = Nil+                        | zero kx1 m2       = intersectBM l2+                        | otherwise         = intersectBM r2+                    intersectBM (Tip kx2 bm2)+                        | kx1 == kx2 = tip kx1 (bm1 .&. bm2)+                        | otherwise = Nil+                    intersectBM Nil = Nil++          go Nil _ = Nil++    equal (KSC ems1) (KSC ems2) = go ems1 ems2+        where+          go (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)+              = (m1 == m2) && (p1 == p2) && (go l1 l2) && (go r1 r2)+          go (Tip kx1 bm1) (Tip kx2 bm2)+              = kx1 == kx2 && bm1 == bm2+          go Nil Nil = True+          go _   _   = False++    nequal (KSC ems1) (KSC ems2) = go ems1 ems2+        where+          go (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)+              = (m1 /= m2) || (p1 /= p2) || (go l1 l2) || (go r1 r2)+          go (Tip kx1 bm1) (Tip kx2 bm2)+              = kx1 /= kx2 || bm1 /= bm2+          go Nil Nil = False+          go _   _   = True++    alter = undefined+    foldr = undefined+    map = undefined+    mapWithKey = undefined+    unionWith = undefined+    unionWithKey = undefined+    differenceWith = undefined+    differenceWithKey = undefined+    intersectionWith = undefined+    intersectionWithKey = undefined+    fromList = undefined+    toList = undefined+    elems = undefined+    keysSet = undefined++{---------------------------------------------------------------------+  Exported API++  The Set API is somewhat different to the Map API so we define the following+  functions to call the IsEMM functions with the type of 'v' as (), hoping that+  GHC will inline away all the empty parameters.+---------------------------------------------------------------------}++null :: (IsKey k) => EnumMapSet k -> Bool+null = EMM.null++size :: (IsKey k) => EnumMapSet k -> Int+size = EMM.size++member ::(IsKey k) => k -> EnumMapSet k -> Bool+member = EMM.member++-- | Lookup a subtree in an 'EnumMapSet'.+--+-- > ems = fromList [1 :& 2 :& K 3, 1 :& 2 :& K 4]+-- > lookup (1 :& K 2) ems == fromList [K 3, K 4]+-- > lookup (1 :& 2 :& K 3) -- ERROR: Use 'member' to check for a key.+--+lookup :: (EMM.SubKey k1 k2 (), IsKey k1, IsKey k2) =>+          k1 -> EnumMapSet k2 -> Maybe (EMM.Result k1 k2 ())+lookup = EMM.lookup++empty :: (IsKey k) => EnumMapSet k+empty = EMM.empty++singleton :: (IsKey k, EMM.SubKey k k (), EMM.Result k k () ~ ()) =>+             k -> EnumMapSet k+singleton !key = EMM.singleton key ()++insert :: (IsKey k, EMM.SubKey k k (), EMM.Result k k () ~ ()) =>+          k -> EnumMapSet k -> EnumMapSet k+insert !key = EMM.insert key ()++insertSub :: (IsKey k1, IsKey k2, EMM.SubKey k1 k2 ()) =>+             k1 -> EMM.Result k1 k2 () -> EnumMapSet k2 -> EnumMapSet k2+insertSub !key = EMM.insert key++delete :: (EMM.SubKey k1 k2 (), IsKey k1, IsKey k2) =>+          k1 -> EnumMapSet k2 -> EnumMapSet k2+delete = EMM.delete++-- This function has not been optimised in any way.+foldr :: (IsKey k) => (k -> t -> t) -> t -> EnumMapSet k -> t+foldr f = EMM.foldrWithKey go+    where+      go k _ z = f k z++-- | @'map' f s@ is the set obtained by applying @f@ to each element of @s@.+--+-- It's worth noting that the size of the result may be smaller if,+-- for some @(x,y)@, @x \/= y && f x == f y@+map :: (IsKey k1, IsKey k2, EMM.SubKey k2 k2 (), EMM.Result k2 k2 () ~ ()) =>+       (k1 -> k2) -> EnumMapSet k1 -> EnumMapSet k2+map f = fromList . List.map f . toList++union :: (IsKey k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k+union = EMM.union++difference :: (IsKey k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k+difference = EMM.difference++intersection :: (IsKey k) => EnumMapSet k -> EnumMapSet k -> EnumMapSet k+intersection = EMM.intersection++{---------------------------------------------------------------------+  Lists+---------------------------------------------------------------------}++fromList :: (IsKey k, EMM.SubKey k k (), EMM.Result k k () ~ ()) =>+            [k] -> EnumMapSet k+fromList xs+    = foldlStrict (\t x -> insert x t) empty xs++toList :: IsKey k => EnumMapSet k -> [k]+toList = foldr (:) []++keys :: IsKey k => EnumMapSet k -> [k]+keys = toList++{---------------------------------------------------------------------+  Instances+---------------------------------------------------------------------}++instance EMM.HasSKey (S k) where+    type Skey (S k) = S k+    toS (S _) = undefined+    toK (S _) = undefined++instance (Enum k1, k1 ~ k2) => EMM.SubKey (S k1) (k2 :& t2) () where+    type Result (S k1) (k2 :& t2) () = EnumMapSet t2++    singleton !(S key) = EMM.KCC . EMM.Tip (fromEnum key)++    lookup (S key') (EMM.KCC emm) = key `seq` go emm+        where+          go (EMM.Bin _ m l r)+             | zero key m = go l+             | otherwise = go r+          go (EMM.Tip kx x)+             = case kx == key of+                 True -> Just x+                 False -> Nothing+          go EMM.Nil = Nothing+          key = fromEnum key'++    insert (S key') val (EMM.KCC emm) = key `seq` EMM.KCC $ go emm+        where+          go t =+              case t of+                EMM.Bin p m l r+                    | nomatch key p m -> EMM.join key (EMM.Tip key val) p t+                    | zero key m      -> EMM.Bin p m (go l) r+                    | otherwise       -> EMM.Bin p m l (go r)+                EMM.Tip ky _+                    | key == ky       -> EMM.Tip key val+                    | otherwise       -> EMM.join key (EMM.Tip key val) ky t+                EMM.Nil               -> EMM.Tip key val+          key = fromEnum key'++    delete (S key') (EMM.KCC emm) = key `seq` EMM.KCC $ go emm+        where+          go t = case t of+                   EMM.Bin p m l r | nomatch key p m -> t+                                   | zero key m      -> EMM.bin p m (go l) r+                                   | otherwise       -> EMM.bin p m l (go r)+                   EMM.Tip ky _    | key == ky       -> EMM.Nil+                                   | otherwise       -> t+                   EMM.Nil                           -> EMM.Nil+          key = fromEnum key'++    insertWith = undefined+    insertWithKey = undefined++instance (Enum k) => EMM.SubKey (S k) (S k) () where+    type Result (S k) (S k) () = ()+    singleton !(S key') _ = KSC $! Tip (prefixOf key) (bitmapOf key)+          where key = fromEnum key'+    lookup = undefined+    insert (S key') _ (KSC ems) =+        key `seq` KSC $ insertBM (prefixOf key) (bitmapOf key) ems+            where key = fromEnum key'+    delete !(S key') (KSC ems) =+        key `seq` KSC $ deleteBM (prefixOf key) (bitmapOf key) ems+          where key = fromEnum key'++    insertWith = undefined+    insertWithKey = undefined++{---------------------------------------------------------------------+  Helper functions+---------------------------------------------------------------------}++insertBM :: Prefix -> BitMap -> EMS k -> EMS k+insertBM !kx !bm t =+    case t of+      Bin p m l r+          | nomatch kx p m -> join kx (Tip kx bm) p t+          | zero kx m      -> Bin p m (insertBM kx bm l) r+          | otherwise      -> Bin p m l (insertBM kx bm r)+      Tip kx' bm'+          | kx' == kx -> Tip kx' (bm .|. bm')+          | otherwise -> join kx (Tip kx bm) kx' t+      Nil -> Tip kx bm++deleteBM :: Prefix -> BitMap -> EMS k -> EMS k+deleteBM !kx !bm t+  = case t of+      Bin p m l r+          | nomatch kx p m -> t+          | zero kx m      -> bin p m (deleteBM kx bm l) r+          | otherwise      -> bin p m l (deleteBM kx bm r)+      Tip kx' bm'+          | kx' == kx -> tip kx (bm' .&. complement bm)+          | otherwise -> t+      Nil -> Nil++join :: Prefix -> EMS k -> Prefix -> EMS k -> EMS k+join p1 t1 p2 t2+  | zero p1 m = Bin p m t1 t2+  | otherwise = Bin p m t2 t1+  where+    m = branchMask p1 p2+    p = mask p1 m+{-# INLINE join #-}++bin :: Prefix -> Mask -> EMS k -> EMS k -> EMS k+bin _ _ l Nil = l+bin _ _ Nil r = r+bin p m l r   = Bin p m l r+{-# INLINE bin #-}++{--------------------------------------------------------------------+  @tip@ assures that we never have empty bitmaps within a tree.+--------------------------------------------------------------------}+tip :: Prefix -> BitMap -> EMS k+tip _ 0 = Nil+tip kx bm = Tip kx bm+{-# INLINE tip #-}++{----------------------------------------------------------------------+  Functions that generate Prefix and BitMap of a Key or a Suffix.++  Commentary and credits can be found with the original code in+  Data/IntSet/Base.hs in 'containers 5.0'.+----------------------------------------------------------------------}++suffixBitMask :: Int+suffixBitMask = bitSize (undefined::Word) - 1+{-# INLINE suffixBitMask #-}++prefixBitMask :: Int+prefixBitMask = complement suffixBitMask+{-# INLINE prefixBitMask #-}++prefixOf :: Int -> Prefix+prefixOf x = x .&. prefixBitMask+{-# INLINE prefixOf #-}++suffixOf :: Int -> Int+suffixOf x = x .&. suffixBitMask+{-# INLINE suffixOf #-}++bitmapOfSuffix :: Int -> BitMap+bitmapOfSuffix s = 1 `shiftLL` s+{-# INLINE bitmapOfSuffix #-}++bitmapOf :: Int -> BitMap+bitmapOf x = bitmapOfSuffix (suffixOf x)+{-# INLINE bitmapOf #-}++bitcount :: Int -> Word -> Int+bitcount a0 x0 = go a0 x0+  where go a 0 = a+        go a x = go (a + 1) (x .&. (x-1))+{-# INLINE bitcount #-}++{----------------------------------------------------------------------+  Folds over a BitMap.++  Commentary and credits can be found with the original code in+  Data/IntSet/Base.hs in 'containers 5.0'.+----------------------------------------------------------------------}++foldrBits :: Int -> (Int -> a -> a) -> a -> Nat -> a++{-# INLINE foldrBits #-}++indexOfTheOnlyBit :: Nat -> Int+{-# INLINE indexOfTheOnlyBit #-}+indexOfTheOnlyBit bitmask =+  I# (lsbArray `indexInt8OffAddr#` unboxInt+                   (intFromNat ((bitmask * magic) `shiftRL` offset)))+  where unboxInt (I# i) = i+#if WORD_SIZE_IN_BITS==32+        magic = 0x077CB531+        offset = 27+        !lsbArray = "\0\1\28\2\29\14\24\3\30\22\20\15\25\17\4\8\31\27\13\23\21\19\16\7\26\12\18\6\11\5\10\9"#+#else+        magic = 0x07EDD5E59A4E28C2+        offset = 58+        !lsbArray = "\63\0\58\1\59\47\53\2\60\39\48\27\54\33\42\3\61\51\37\40\49\18\28\20\55\30\34\11\43\14\22\4\62\57\46\52\38\26\32\41\50\36\17\19\29\10\13\21\56\45\25\31\35\16\9\12\44\24\15\8\23\7\6\5"#+#endif+lowestBitMask :: Nat -> Nat+lowestBitMask x = x .&. negate x+{-# INLINE lowestBitMask #-}++revNat :: Nat -> Nat+#if WORD_SIZE_IN_BITS==32+revNat x1 = case ((x1 `shiftRL` 1) .&. 0x55555555) .|. ((x1 .&. 0x55555555) `shiftLL` 1) of+              x2 -> case ((x2 `shiftRL` 2) .&. 0x33333333) .|. ((x2 .&. 0x33333333) `shiftLL` 2) of+                 x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F) `shiftLL` 4) of+                   x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF) .|. ((x4 .&. 0x00FF00FF) `shiftLL` 8) of+                     x5 -> ( x5 `shiftRL` 16             ) .|. ( x5               `shiftLL` 16);+#else+revNat x1 = case ((x1 `shiftRL` 1) .&. 0x5555555555555555) .|. ((x1 .&. 0x5555555555555555) `shiftLL` 1) of+              x2 -> case ((x2 `shiftRL` 2) .&. 0x3333333333333333) .|. ((x2 .&. 0x3333333333333333) `shiftLL` 2) of+                 x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F0F0F0F0F) `shiftLL` 4) of+                   x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF00FF00FF) .|. ((x4 .&. 0x00FF00FF00FF00FF) `shiftLL` 8) of+                     x5 -> case ((x5 `shiftRL` 16) .&. 0x0000FFFF0000FFFF) .|. ((x5 .&. 0x0000FFFF0000FFFF) `shiftLL` 16) of+                       x6 -> ( x6 `shiftRL` 32             ) .|. ( x6               `shiftLL` 32);+#endif+foldrBits prefix f z bitmap = go (revNat bitmap) z+  where go bm acc | bm == 0 = acc+                  | otherwise = case lowestBitMask bm of+                                  bitmask -> bitmask `seq` case indexOfTheOnlyBit bitmask of+                                    bi -> bi `seq` go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS-1)-bi)) acc)
enummapmap.cabal view
@@ -1,5 +1,5 @@ name:               enummapmap-version:            0.1.0+version:            0.2.0 synopsis:           Map of maps using Enum types as keys description:        This package provides 'maps of maps' using Enum types as                     keys.  The code is based upon Data.IntMap in@@ -20,7 +20,7 @@ Library    exposed-modules: Data.EnumMapMap.Lazy, Data.EnumMapMap.Strict,                     Data.EnumMapSet-   other-modules:   Data.EnumMapMap.Base+   other-modules:   Data.EnumMapMap.Base, Data.EnumMapSet.Base    build-depends:   base >= 4.0 && < 5,                     deepseq >= 1.2 && < 1.4,                     ghc-prim
test/EnumMapMapVsIntMap.hs view
@@ -417,3 +417,23 @@              runPropDuoL4 (IM.intersectionWithKey f)                              (EMM.intersectionWithKey                                      (\(k :& _ :& _ :& K _) a b -> f k a b))++    describe "keys" $ do+        prop "Level 1" $+             runProp (IM.keys) (map (\(K k) -> k) . EMM.keys)+        prop "Level 2" $+             runProp2 (IM.keys) (map (\(k :& _) -> k) . EMM.keys)+        prop "Level 3" $+             runProp3 (IM.keys) (map (\(k :& _) -> k) . EMM.keys)+        prop "Level 4" $+             runProp4 (IM.keys) (map (\(k :& _) -> k) . EMM.keys)++    describe "elems" $ do+        prop "Level 1" $+             runProp (IM.elems) (EMM.elems)+        prop "Level 2" $+             runProp2 (IM.elems) (EMM.elems)+        prop "Level 3" $+             runProp3 (IM.elems) (EMM.elems)+        prop "Level 4" $+             runProp4 (IM.elems) (EMM.elems)
test/EnumMapSetVsIntSet.hs view
@@ -10,21 +10,21 @@  import qualified Data.IntSet as IS -import           Data.EnumMapSet(EnumMapSet, (:&)(..), K(..))+import           Data.EnumMapSet(EnumMapSet, (:&)(..), S(..)) import qualified Data.EnumMapSet as EMS -type TestSet1 = EnumMapSet (K Int)-type TestSet2 = EnumMapSet (Int :& K Int)-type TestSet3 = EnumMapSet (Int :& Int :& K Int)+type TestSet1 = EnumMapSet (S Int)+type TestSet2 = EnumMapSet (Int :& S Int)+type TestSet3 = EnumMapSet (Int :& Int :& S Int) -list2l1 :: [Int] -> [K Int]-list2l1 = map (\k -> K k)+list2l1 :: [Int] -> [S Int]+list2l1 = map S -list2l2 :: Int -> [Int] -> [Int :& K Int]-list2l2 k1 = map (\k -> k :& K k1)+list2l2 :: Int -> [Int] -> [Int :& S Int]+list2l2 k1 = map (\k -> k :& S k1) -list2l3 :: Int -> Int -> [Int] -> [Int :& Int :& K Int]-list2l3 k1 k2 = map (\k -> k :& k1 :& K k2)+list2l3 :: Int -> Int -> [Int] -> [Int :& Int :& S Int]+list2l3 k1 k2 = map (\k -> k :& k1 :& S k2)  runProp :: Eq t =>            (IS.IntSet -> t)@@ -152,29 +152,29 @@      describe "insert" $ do       prop "Level 1" $ \k ->-          runPropL (IS.insert k) (EMS.insert $ K k)+          runPropL (IS.insert k) (EMS.insert $ S k)       prop "Level 2" $ \k k1 ->-          runPropL2 (IS.insert k) (EMS.insert $ k :& K k1) k1+          runPropL2 (IS.insert k) (EMS.insert $ k :& S k1) k1       prop "Level 3" $ \k k1 k2 ->-          runPropL3 (IS.insert k) (EMS.insert $ k :& k1 :& K k2) k1 k2+          runPropL3 (IS.insert k) (EMS.insert $ k :& k1 :& S k2) k1 k2      describe "delete" $ do       prop "Level 1" $ \k ->-          runPropL (IS.delete k) (EMS.delete $ K k)+          runPropL (IS.delete k) (EMS.delete $ S k)       prop "Level 2" $ \k k1 ->-          runPropL2 (IS.delete k) (EMS.delete $ k :& K k1) k1+          runPropL2 (IS.delete k) (EMS.delete $ k :& S k1) k1       prop "Level 3" $ \k k1 k2 ->-          runPropL3 (IS.delete k) (EMS.delete $ k :& k1 :& K k2) k1 k2+          runPropL3 (IS.delete k) (EMS.delete $ k :& k1 :& S k2) k1 k2      describe "map" $ do       let f a = a + 1       prop "Level 1" $-           runPropL (IS.map f) (EMS.map (\(K k) -> K $ f k))+           runPropL (IS.map f) (EMS.map (\(S k) -> S $ f k))       prop "Level 2" $-           runPropL2 (IS.map f) (EMS.map (\(k :& K k1) -> f k :& K k1))+           runPropL2 (IS.map f) (EMS.map (\(k :& S k1) -> f k :& S k1))       prop "Level 3" $            runPropL3 (IS.map f)-                         (EMS.map (\(k :& k2 :& K k1) -> f k :& k2 :& K k1))+                         (EMS.map (\(k :& k2 :& S k1) -> f k :& k2 :& S k1))      describe "union" $ do       prop "Level 1" $
test/UnitEnumMapMap.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, TypeOperators #-}+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, ScopedTypeVariables, TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  import           Control.Monad (liftM, liftM2)@@ -7,6 +7,7 @@ import           Test.Hspec.QuickCheck (prop) import           Test.HUnit import           Test.QuickCheck (Arbitrary, arbitrary, shrink)+import qualified Data.EnumMapSet as EMS  #ifdef LAZY import           Data.EnumMapMap.Lazy(EnumMapMap, (:&)(..), K(..))@@ -25,15 +26,26 @@     arbitrary = liftM K arbitrary  newtype ID1 = ID1 Int-    deriving (Show, Enum, Arbitrary)+    deriving (Show, Enum, Arbitrary, Eq, Num) newtype ID2 = ID2 Int-    deriving (Show, Enum, Arbitrary)+    deriving (Show, Enum, Arbitrary, Eq, Num) newtype ID3 = ID3 Int-    deriving (Show, Enum, Arbitrary)+    deriving (Show, Enum, Arbitrary, Eq, Num) +type TestKey1 = K ID1+type TestEmm1 = EnumMapMap TestKey1 Int+type TestKey2 = ID2 :& K ID1+type TestEmm2 = EnumMapMap TestKey2 Int type TestKey3 = ID3 :& ID2 :& K ID1 type TestEmm3 = EnumMapMap TestKey3 Int +type I = K Int++-- Functions that are part of 'SubKey' class can't cope with @K 1@ because GHC+-- doesn't know it's also an 'Int'.+k :: Int -> K Int+k = K+ tens :: [Int] tens = [1, 10, 100, 1000, 10000, 100000, 1000000] @@ -49,23 +61,23 @@ alls :: [Int] alls = [1, 2..1000] -l1tens :: EnumMapMap (K Int) Int-l1tens = EMM.fromList $ map (\(k, v) -> (K k, v)) $ zip [1..7] tens-l2tens :: EnumMapMap (Int :& K Int) Int+l1tens :: EnumMapMap I Int+l1tens = EMM.fromList $ map (\(key, v) -> (K key, v)) $ zip [1..7] tens+l2tens :: EnumMapMap (Int :& I) Int l2tens = EMM.fromList $ zip (do                               k1 <- [1, 2]                               k2 <- [1..7]                               return $ k1 :& K k2) $ cycle tens  l1odds :: EnumMapMap (K Int) Int-l1odds = EMM.fromList $ map (\(k, v) -> (K k, v)) $ zip odds odds+l1odds = EMM.fromList $ map (\(key, v) -> (K key, v)) $ zip odds odds l2odds :: EnumMapMap (Int :& K Int) Int l2odds = EMM.fromList $ zip (do                               k1 <- fewOdds                               k2 <- fewOdds                               return $ k1 :& K k2) $ cycle odds l1evens :: EnumMapMap (K Int) Int-l1evens = EMM.fromList $ map (\(k, v) -> (K k, v)) $ zip evens evens+l1evens = EMM.fromList $ map (\(key, v) -> (K key, v)) $ zip evens evens  l1alls :: EnumMapMap (K Int) Int l1alls = EMM.fromList $ zip (map K alls) alls@@ -95,27 +107,56 @@       it "is the inverse of toList on 2 levels" $            (EMM.fromList $ EMM.toList l2odds) @?= l2odds +    describe "lookup" $ do+      let emm3 :: TestEmm3+          emm3 = EMM.fromList [(ID3 1 :& ID2 2 :& (K $ ID1 3), 4)]+          key3 = ID3 1 :& ID2 2 :& (K $ ID1 3)+      describe "looks up a subtree" $ do+         let emm2 :: EnumMapMap (Int :& K Int) Int+             emm2 = EMM.fromList [(1 :& k 2, 5)]+             key1 :: K ID3+             key1 = K $ ID3 1+             key2 :: ID3 :& K ID2+             key2 = ID3 1 :& (K $ ID2 2)+         it "First level of level 2" $+            (EMM.lookup (K 1) emm2) @?= (Just $ EMM.fromList [(K 2, 5)])+         it "1 level of level 3" $+            (EMM.lookup key1 emm3) @?= (Just $+                                     EMM.fromList [(ID2 2 :& (K $ ID1 3), 4)])+         it "2 levels of level 3" $+            (EMM.lookup key2 emm3) @?= (Just $ EMM.fromList [(K $ ID1 3, 4)])+      it "looks up a value" $+         (EMM.lookup key3 emm3) @?= Just 4++    describe "singleton" $ do+      let emm2 :: EnumMapMap (ID1 :& K ID2) String+          emm2 = EMM.fromList [(ID1 1 :& (K $ ID2 2), "a")]+      it "creates an EnumMapMap with one value" $+         (EMM.singleton (ID1 1 :& (K $ ID2 2)) "a") @?= emm2+      it "creates an EnumMapMap with a sub EnumMapMap" $+         (EMM.singleton (K $ ID1 1) $ EMM.singleton (K $ ID2 2) "a") @?= emm2+     describe "insert" $ do       describe "Level 1" $ do         it "creates a value in an empty EMM" $-           EMM.insert (K 1) 1 EMM.empty @?=-           (EMM.fromList [(K 1, 1)]-                           :: EnumMapMap (K Int) Int)+           EMM.insert (k 1) 1 EMM.empty @?=+           (EMM.fromList [(k 1, 1)]+                           :: EnumMapMap I Int)         it "adds another value to an EMM" $            let                emm :: EnumMapMap (K Int) Int-               emm = EMM.fromList [(K 2, 2)] in-           EMM.insert (K 1) 1 emm @?=-              EMM.fromList [(K 1, 1), (K 2, 2)]+               emm = EMM.fromList [(k 2, 2)] in+           EMM.insert (k 1) 1 emm @?=+              EMM.fromList [(k 1, 1), (k 2, 2)]         it "overwrites a value with the same key in an EMM" $            let emm :: EnumMapMap (K Int) Int                emm = EMM.fromList [(K 1, 1), (K 2, 2)] in-           EMM.insert (K 1) 3 emm @?=+           EMM.insert (k 1) 3 emm @?=               EMM.fromList [(K 1, 3), (K 2, 2)]          describe "Level 2" $ do           it "creates a value in an empty EMM" $-             EMM.insert (1 :& K 1) 1 EMM.empty @?=+             EMM.insert ((1 :: Int) :& k 1) 1 EMM.empty @?=                              (EMM.fromList [(1 :& K 1, 1)]                                   :: EnumMapMap (Int :& K Int) Int)           it "adds another value to an EMM on level 1" $@@ -123,67 +164,84 @@                  emm :: EnumMapMap (Int :& K Int) Int                  emm = EMM.fromList [(1 :& K 2, 2)]              in-               EMM.insert (1 :& K 1) 1 emm @?=+               EMM.insert ((1 :: Int) :& k 1) 1 emm @?=                EMM.fromList [(1 :& K 1, 1), (1 :& K 2, 2)]           it "adds another value to an EMM on level 2" $              let                  emm :: EnumMapMap (Int :& K Int) Int                  emm = EMM.fromList [(1 :& K 1, 1)]              in-               EMM.insert (2 :& K 2) 2 emm @?=+               EMM.insert ((2 :: Int) :& k 2) 2 emm @?=                EMM.fromList [(1 :& K 1, 1), (2 :& K 2, 2)] +        describe "Subtrees" $ do+          let emm2 :: TestEmm2+              emm2 = EMM.fromList [(ID2 2 :& (K $ ID1 3), 4)]+              emm1 :: TestEmm1+              emm1 = EMM.fromList [(K $ ID1 4, 12)]+          it "inserts a L1 into an empty L3 EMM" $+             EMM.insert (ID3 2 :& (K $ ID2 3)) emm1 EMM.empty @?=+                EMM.fromList [(ID3 2 :& ID2 3 :& (K $ ID1 4), 12)]+          it "inserts a L2 into an empty L3 EMM" $+             EMM.insert (K $ ID3 1) emm2 EMM.empty @?=+                EMM.fromList [(ID3 1 :& ID2 2 :& (K $ ID1 3), 4)]+     describe "insertWithKey" $ do       let undef = undefined -- fail if this is called       describe "Level 1" $ do         it "creates a value in an empty EMM" $-           EMM.insertWithKey undef (K 1) 1 EMM.empty @?=-                  (EMM.fromList [(K 1, 1)]+           EMM.insertWithKey undef (k 1) 1 EMM.empty @?=+                  (EMM.fromList [(k 1, 1)]                        :: EnumMapMap (K Int) Int)         it "adds another value to an EMM" $            let                emm :: EnumMapMap (K Int) Int                emm = EMM.fromList [(K 2, 2)] in-           EMM.insertWithKey undef (K 1) 1 emm @?=-              EMM.fromList [(K 1, 1), (K 2, 2)]+           EMM.insertWithKey undef (k 1) 1 emm @?=+              EMM.fromList [(k 1, 1), (k 2, 2)]         it "applies the function when overwriting" $            let emm :: EnumMapMap (K Int) Int-               emm = EMM.fromList [(K 1, 1), (K 2, 4)]+               emm = EMM.fromList [(k 1, 1), (k 2, 4)]                f (K key1) o n = key1 * (o + n)            in-             EMM.insertWithKey f (K 2) 3 emm @?=-                EMM.fromList [(K 1, 1), (K 2, 14)]+             EMM.insertWithKey f (k 2) 3 emm @?=+                EMM.fromList [(k 1, 1), (k 2, 14)]        describe "Level 2" $ do         it "creates a value in an empty EMM" $-           EMM.insertWithKey undef (1 :& K 1) 1 EMM.empty @?=-                  (EMM.fromList [(1 :& K 1, 1)]-                           :: EnumMapMap (Int :& K Int) Int)+           EMM.insertWithKey undef (ID2 1 :& k 1) 1 EMM.empty @?=+                  (EMM.fromList [(ID2 1 :& k 1, 1)]+                           :: EnumMapMap (ID2 :& K Int) Int)         it "adds another value to an EMM on level 1" $            let-               emm :: EnumMapMap (Int :& K Int) Int-               emm = EMM.fromList [(1 :& K 2, 2)]+               emm :: EnumMapMap (ID2 :& K Int) Int+               emm = EMM.fromList [(ID2 1 :& k 2, 2)]            in-             EMM.insertWithKey undef (1 :& K 1) 1 emm @?=-                EMM.fromList [(1 :& K 1, 1), (1 :& K 2, 2)]+             EMM.insertWithKey undef (ID2 1 :& k 1) 1 emm @?=+                EMM.fromList [(ID2 1 :& K 1, 1), (ID2 1 :& K 2, 2)]         it "adds another value to an EMM on level 2" $            let-               emm :: EnumMapMap (Int :& K Int) Int-               emm = EMM.fromList [(1 :& K 1, 1)]+               emm :: EnumMapMap (ID2 :& K Int) Int+               emm = EMM.fromList [(ID2 1 :& k 1, 1)]            in-             EMM.insertWithKey undef (2 :& K 2) 2 emm @?=-                EMM.fromList [(1 :& K 1, 1), (2 :& K 2, 2)]+             EMM.insertWithKey undef (ID2 2 :& k 2) 2 emm @?=+                EMM.fromList [(ID2 1 :& K 1, 1), (ID2 2 :& K 2, 2)]         it "applies the function when overwriting" $            let emm :: EnumMapMap (Int :& K Int) Int-               emm = EMM.fromList [(2 :& K 3, 1), (2 :& K 4, 5)]+               emm = EMM.fromList [((2 :: Int) :& K 3, 1), ((2 :: Int) :& K 4, 5)]                f (k1 :& K k2) o n = (k1 + k2) * (o + n)            in-             EMM.insertWithKey f (2 :& K 4) 3 emm @?=-                EMM.fromList [(2 :& K 3, 1), (2 :& K 4, 48)]+             EMM.insertWithKey f (2 :& k 4) 3 emm @?=+                EMM.fromList [((2 :: Int) :& K 3, 1), ((2 :: Int) :& K 4, 48)]      describe "delete" $ do-      prop "leaves no empty subtrees" $ \k l ->-          not $ EMM.emptySubTrees $ EMM.delete k $ (EMM.fromList l :: TestEmm3)+      describe "leaves no empty subtrees" $ do+        prop "Full key" $ \(key :: ID3 :& ID2 :& K ID1) l ->+          not $ EMM.emptySubTrees $ EMM.delete key $ (EMM.fromList l :: TestEmm3)+        prop "2 dimensional key" $ \(key :: ID3 :& K ID2) l ->+          not $ EMM.emptySubTrees $ EMM.delete key $ (EMM.fromList l :: TestEmm3)+        prop "1 dimensional key" $ \(key :: K ID3) l ->+          not $ EMM.emptySubTrees $ EMM.delete key $ (EMM.fromList l :: TestEmm3)      describe "alter" $ do       let f b1 b2 n v = case v of@@ -191,8 +249,8 @@                           Just v' -> case b1 of                                        True  -> Just $ if b2 then v' else n                                        False -> Nothing-      prop "leaves no empty subtrees" $ \k l b1 b2 n ->-          not $ EMM.emptySubTrees $ EMM.alter (f b1 b2 n) k $+      prop "leaves no empty subtrees" $ \key l b1 b2 n ->+          not $ EMM.emptySubTrees $ EMM.alter (f b1 b2 n) key $                   (EMM.fromList l :: TestEmm3)      describe "foldrWithKey" $ do@@ -246,4 +304,13 @@             go32 l = emm == (EMM.joinKey $ EMM.splitKey EMM.d2 emm)                 where emm = EMM.fromList l         prop "Level 3, depth = 2" go32++      describe "keysSet" $ do+        describe "produces same result as keys" $ do+          let gol1 :: [(K Int, Int)] -> Bool+              gol1 list = EMM.keys emm == (map EMM.toK $ EMS.toList $ EMM.keysSet emm)+                  where+                    emm = EMM.fromList list+          prop "Level 1" gol1+