git.iko.soy/typeable/ordered-containers
on master help sign in
admit that not everything can be done super fast
f163377Daniel Wagner
Data/Map/Ordered.hs+80−2
@@ -1,8 +1,9 @@
1{-# LANGUAGE DeriveDataTypeable #-}
1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveFunctor #-}
2{-# LANGUAGE DeriveFunctor #-}
3
3
4−-- | An 'OMap' behaves much like a 'Map', with all the same asymptotics, but
4+-- | An 'OMap' behaves much like a 'Map', with mostly the same asymptotics, but
5−-- also remembers the order that keys were inserted.
5+-- also remembers the order that keys were inserted. All operations whose
6+-- asymptotics are worse than 'Map' have documentation saying so.
6module Data.Map.Ordered
7module Data.Map.Ordered
7 ( OMap
8 ( OMap
8 -- * Trivial maps
9 -- * Trivial maps
@@ -18,8 +19,10 @@ module Data.Map.Ordered
18 --
19 --
19 -- * If both sides contain the same key, the tuple's value wins
20 -- * If both sides contain the same key, the tuple's value wins
20 , (<|), (|<), (>|), (|>)
21 , (<|), (|<), (>|), (|>)
22+ , (<>|), (|<>), unionWithL, unionWithR
21 -- * Deletion
23 -- * Deletion
22 , delete, filter, (\\)
24 , delete, filter, (\\)
25+ , (|/\), (/\|), intersectionWith
23 -- * Query
26 -- * Query
24 , null, size, member, notMember, lookup
27 , null, size, member, notMember, lookup
25 -- * Indexing
28 -- * Indexing
@@ -67,10 +70,21 @@ oMapDataType = mkDataType "Data.Map.Ordered.Map" [fromListConstr]
67
70
68infixr 5 <|, |< -- copy :
71infixr 5 <|, |< -- copy :
69infixl 5 >|, |>
72infixl 5 >|, |>
73+infixr 6 <>|, |<> -- copy <>
70
74
71(<|) , (|<) :: Ord k => (,) k v -> OMap k v -> OMap k v
75(<|) , (|<) :: Ord k => (,) k v -> OMap k v -> OMap k v
72(>|) , (|>) :: Ord k => OMap k v -> (,) k v -> OMap k v
76(>|) , (|>) :: Ord k => OMap k v -> (,) k v -> OMap k v
73
77
78+-- | When a key occurs in both maps, prefer the value from the first map.
79+--
80+-- See asymptotics of 'unionWithR'.
81+(<>|) :: Ord k => OMap k v -> OMap k v -> OMap k v
82+
83+-- | When a key occurs in both maps, prefer the value from the first map.
84+--
85+-- See asymptotics of 'unionWithL'.
86+(|<>) :: Ord k => OMap k v -> OMap k v -> OMap k v
87+
74(k, v) <| OMap tvs kvs = OMap (M.insert k (t, v) tvs) (M.insert t (k, v) kvs) where
88(k, v) <| OMap tvs kvs = OMap (M.insert k (t, v) tvs) (M.insert t (k, v) kvs) where
75 t = maybe (nextLowerTag kvs) fst (M.lookup k tvs)
89 t = maybe (nextLowerTag kvs) fst (M.lookup k tvs)
76
90
@@ -85,7 +99,41 @@ o >| (k, v) = OMap (M.insert k (t, v) tvs) (M.insert t (k, v) kvs) where
85OMap tvs kvs |> (k, v) = OMap (M.insert k (t, v) tvs) (M.insert t (k, v) kvs) where
99OMap tvs kvs |> (k, v) = OMap (M.insert k (t, v) tvs) (M.insert t (k, v) kvs) where
86 t = maybe (nextHigherTag kvs) fst (M.lookup k tvs)
100 t = maybe (nextHigherTag kvs) fst (M.lookup k tvs)
87
101
102+(<>|) = unionWithR (const const)
103+(|<>) = unionWithL (const const)
104+
105+-- | Take the union. The first 'OMap' \'s argument's indices are lower than the
106+-- second. If a key appears in both maps, the first argument's index takes
107+-- precedence, and the supplied function is used to combine the values.
108+--
109+-- /O(r*log(r))/ where /r/ is the size of the result
110+unionWithL :: Ord k => (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
111+unionWithL = unionWithInternal (\t t' -> t )
112+
113+-- | Take the union. The first 'OMap' \'s argument's indices are lower than the
114+-- second. If a key appears in both maps, the second argument's index takes
115+-- precedence, and the supplied function is used to combine the values.
116+--
117+-- /O(r*log(r))/ where /r/ is the size of the result
118+unionWithR :: Ord k => (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
119+unionWithR = unionWithInternal (\t t' -> t')
120+
121+unionWithInternal :: Ord k => (Tag -> Tag -> Tag) -> (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
122+unionWithInternal fT fKV (OMap tvs kvs) (OMap tvs' kvs') = fromTV tvs'' where
123+ bump = case maxTag kvs of
124+ Nothing -> 0
125+ Just k -> -k-1
126+ bump' = case minTag kvs' of
127+ Nothing -> 0
128+ Just k -> -k
129+ tvs'' = M.unionWithKey (\k (t,v) (t',v') -> (fT t t', fKV k v v'))
130+ (fmap (\(t,v) -> (bump +t,v)) tvs )
131+ (fmap (\(t,v) -> (bump'+t,v)) tvs')
132+
88-- | @m \\\\ n@ deletes all the keys that exist in @n@ from @m@
133-- | @m \\\\ n@ deletes all the keys that exist in @n@ from @m@
134+--
135+-- /O(m*log(n))/ where /m/ is the size of the smaller map and /n/ is the size
136+-- of the larger map.
89(\\) :: Ord k => OMap k v -> OMap k v' -> OMap k v
137(\\) :: Ord k => OMap k v -> OMap k v' -> OMap k v
90o@(OMap tvs kvs) \\ o'@(OMap tvs' kvs') = if size o < size o'
138o@(OMap tvs kvs) \\ o'@(OMap tvs' kvs') = if size o < size o'
91 then filter (const . (`notMember` o')) o
139 then filter (const . (`notMember` o')) o
@@ -129,6 +177,36 @@ delete k o@(OMap tvs kvs) = case M.lookup k tvs of
129 Nothing -> o
177 Nothing -> o
130 Just (t, _) -> OMap (M.delete k tvs) (M.delete t kvs)
178 Just (t, _) -> OMap (M.delete k tvs) (M.delete t kvs)
131
179
180+-- | Intersection. (The @/\\@ is intended to look a bit like the standard
181+-- mathematical notation for set intersection.)
182+--
183+-- See asymptotics of 'intersectionWith'.
184+(/\|) :: Ord k => OMap k v -> OMap k v' -> OMap k v
185+o /\| o' = intersectionWith (\k v' v -> v) o' o
186+
187+-- | Intersection. (The @/\\@ is intended to look a bit like the standard
188+-- mathematical notation for set intersection.)
189+--
190+-- See asymptotics of 'intersectionWith'.
191+(|/\) :: Ord k => OMap k v -> OMap k v' -> OMap k v
192+o |/\ o' = intersectionWith (\k v v' -> v) o o'
193+
194+-- | Take the intersection. The first 'OMap' \'s argument's indices are used for
195+-- the result.
196+--
197+-- /O(m*log(n\/(m+1)) + r*log(r))/ where /m/ is the size of the smaller map, /n/
198+-- is the size of the larger map, and /r/ is the size of the result.
199+intersectionWith ::
200+ Ord k =>
201+ (k -> v -> v' -> v'') ->
202+ OMap k v -> OMap k v' -> OMap k v''
203+intersectionWith f (OMap tvs kvs) (OMap tvs' kvs') = fromTV
204+ $ M.intersectionWithKey (\k (t,v) (t',v') -> (t, f k v v')) tvs tvs'
205+
206+fromTV :: Ord k => Map k (Tag, v) -> OMap k v
207+fromTV tvs = OMap tvs kvs where
208+ kvs = M.fromList [(t,(k,v)) | (k,(t,v)) <- M.toList tvs]
209+
132findIndex :: Ord k => k -> OMap k v -> Maybe Index
210findIndex :: Ord k => k -> OMap k v -> Maybe Index
133findIndex k o@(OMap tvs kvs) = do
211findIndex k o@(OMap tvs kvs) = do
134 (t, _) <- M.lookup k tvs
212 (t, _) <- M.lookup k tvs
Data/Set/Ordered.hs+31−4
@@ -1,7 +1,8 @@
1{-# LANGUAGE DeriveDataTypeable #-}
1{-# LANGUAGE DeriveDataTypeable #-}
2
2
3−-- | An 'OSet' behaves much like a 'Set', with all the same asymptotics, but
3+-- | An 'OSet' behaves much like a 'Set', with mostly the same asymptotics, but
4−-- also remembers the order that values were inserted.
4+-- also remembers the order that values were inserted. All operations whose
5+-- asymptotics are worse than 'Set' have documentation saying so.
5module Data.Set.Ordered
6module Data.Set.Ordered
6 ( OSet
7 ( OSet
7 -- * Trivial sets
8 -- * Trivial sets
@@ -19,7 +20,7 @@ module Data.Set.Ordered
19 -- * Query
20 -- * Query
20 , null, size, member, notMember
21 , null, size, member, notMember
21 -- * Deletion
22 -- * Deletion
22− , delete, filter, (\\)
23+ , delete, filter, (\\), (|/\), (/\|)
23 -- * Indexing
24 -- * Indexing
24 , Index, findIndex, elemAt
25 , Index, findIndex, elemAt
25 -- * List conversions
26 -- * List conversions
@@ -69,7 +70,14 @@ infixr 6 <>|, |<> -- copy <>
69
70
70(<|) , (|<) :: Ord a => a -> OSet a -> OSet a
71(<|) , (|<) :: Ord a => a -> OSet a -> OSet a
71(>|) , (|>) :: Ord a => OSet a -> a -> OSet a
72(>|) , (|>) :: Ord a => OSet a -> a -> OSet a
73+
74+-- | /O(m*log(n)+n)/, where /m/ is the size of the smaller set and /n/ is the
75+-- size of the larger set.
76+(<>|) :: Ord a => OSet a -> OSet a -> OSet a
77+
78+-- | /O(m*log(n)+n)/, where /m/ is the size of the smaller set and /n/ is the
79+-- size of the larger set.
72−(<>|), (|<>) :: Ord a => OSet a -> OSet a -> OSet a
80+(|<>) :: Ord a => OSet a -> OSet a -> OSet a
73
81
74v <| o@(OSet ts vs)
82v <| o@(OSet ts vs)
75 | v `member` o = o
83 | v `member` o = o
@@ -110,11 +118,30 @@ unsafeMappend (OSet ts vs) (OSet ts' vs')
110
118
111-- | Set difference: @r \\\\ s@ deletes all the values in @s@ from @r@. The
119-- | Set difference: @r \\\\ s@ deletes all the values in @s@ from @r@. The
112-- order of @r@ is unchanged.
120-- order of @r@ is unchanged.
121+--
122+-- /O(m*log(n))/ where /m/ is the size of the smaller set and /n/ is the size
123+-- of the larger set.
113(\\) :: Ord a => OSet a -> OSet a -> OSet a
124(\\) :: Ord a => OSet a -> OSet a -> OSet a
114o@(OSet ts vs) \\ o'@(OSet ts' vs') = if size o < size o'
125o@(OSet ts vs) \\ o'@(OSet ts' vs') = if size o < size o'
115 then filter (`notMember` o') o
126 then filter (`notMember` o') o
116 else foldr delete o vs'
127 else foldr delete o vs'
117
128
129+-- | Intersection. (@/\\@ is meant to look a bit like the standard mathematical
130+-- notation for intersection.)
131+--
132+-- /O(m*log(n\/(m+1)) + r*log(r))/, where /m/ is the size of the smaller set,
133+-- /n/ the size of the larger set, and /r/ the size of the result.
134+(|/\) :: Ord a => OSet a -> OSet a -> OSet a
135+OSet ts vs |/\ OSet ts' vs' = OSet ts'' vs'' where
136+ ts'' = M.intersection ts ts'
137+ vs'' = M.fromList [(t, v) | (v, t) <- M.toList ts]
138+
139+-- | @flip ('|/\')@
140+--
141+-- See asymptotics of '|/\'.
142+(/\|) :: Ord a => OSet a -> OSet a -> OSet a
143+(/\|) = flip (/\|)
144+
118empty :: OSet a
145empty :: OSet a
119empty = OSet M.empty M.empty
146empty = OSet M.empty M.empty
120
147