1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE NamedFieldPuns #-}
3 {-# LANGUAGE StandaloneDeriving #-}
4 {-# LANGUAGE RecordWildCards #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
7 -- | This module implements a strict 'TreeMap',
8 -- which is like a 'Map'
9 -- but whose key is now a 'NonEmpty' list of 'Map' keys (a 'Path')
10 -- enabling the possibility to gather mapped values
11 -- by 'Path' prefixes (inside a 'Node').
12 module Data.TreeMap.Strict where
14 import Control.Applicative (Applicative(..))
15 import Control.DeepSeq (NFData(..))
16 import Control.Monad (Monad(..))
18 import Data.Data (Data)
20 import Data.Foldable (Foldable, foldMap)
21 import Data.Function (($), (.), const, flip, id)
22 import Data.Functor (Functor(..), (<$>))
23 import qualified Data.List
24 import qualified Data.List.NonEmpty
25 import Data.List.NonEmpty (NonEmpty(..))
26 import Data.Map.Strict (Map)
27 import qualified Data.Map.Strict as Map
28 import Data.Maybe (Maybe(..), maybe)
29 import Data.Monoid (Monoid(..))
30 import Data.Ord (Ord(..))
31 import Data.Semigroup (Semigroup(..))
32 import qualified Data.Strict.Maybe as Strict
33 import Data.Traversable (Traversable(..))
34 import Data.Typeable (Typeable)
35 import Prelude (Int, Num(..), seq)
36 import Text.Show (Show(..))
38 -- @Data.Strict@ orphan instances
39 deriving instance Data x => Data (Strict.Maybe x)
40 deriving instance Typeable Strict.Maybe
41 instance Semigroup x => Semigroup (Strict.Maybe x) where
42 Strict.Just x <> Strict.Just y = Strict.Just (x <> y)
43 x <> Strict.Nothing = x
44 Strict.Nothing <> y = y
45 instance Semigroup x => Monoid (Strict.Maybe x) where
46 mempty = Strict.Nothing
48 instance NFData x => NFData (Strict.Maybe x) where
49 rnf Strict.Nothing = ()
50 rnf (Strict.Just x) = rnf x
55 = TreeMap (Map k (Node k x))
56 deriving (Data, Eq, Ord, Show, Typeable)
58 instance (Ord k, Semigroup v) => Semigroup (TreeMap k v) where
60 instance (Ord k, Monoid v) => Monoid (TreeMap k v) where
62 mappend = union mappend
63 -- mconcat = Data.List.foldr mappend mempty
64 instance Ord k => Functor (TreeMap k) where
65 fmap f (TreeMap m) = TreeMap $ fmap (fmap f) m
66 instance Ord k => Foldable (TreeMap k) where
67 foldMap f (TreeMap m) = foldMap (foldMap f) m
68 instance Ord k => Traversable (TreeMap k) where
69 traverse f (TreeMap m) = TreeMap <$> traverse (traverse f) m
70 instance (Ord k, NFData k, NFData x) => NFData (TreeMap k x) where
71 rnf (TreeMap m) = rnf m
75 -- | A 'Path' is a non-empty list of 'Map' keys.
78 path :: k -> [k] -> Path k
82 list = Data.List.NonEmpty.toList
84 reverse :: Path k -> Path k
85 reverse = Data.List.NonEmpty.reverse
90 { node_size :: !Int -- ^ The number of non-'Strict.Nothing' 'node_value's reachable from this 'Node'.
91 , node_value :: !(Strict.Maybe x) -- ^ Some value, or 'Strict.Nothing' if this 'Node' is intermediary.
92 , node_descendants :: !(TreeMap k x) -- ^ Descendants 'Node's.
93 } deriving (Data, Eq, Ord, Show, Typeable)
95 instance (Ord k, Semigroup v) => Semigroup (Node k v) where
97 Node{node_value=x0, node_descendants=m0}
98 Node{node_value=x1, node_descendants=m1} =
99 node (x0 <> x1) (union const m0 m1)
100 instance (Ord k, Semigroup v) => Monoid (Node k v) where
101 mempty = node Strict.Nothing (TreeMap mempty)
103 -- mconcat = Data.List.foldr mappend mempty
104 instance Ord k => Functor (Node k) where
105 fmap f Node{node_value=x, node_descendants=m, node_size} =
107 { node_value = fmap f x
108 , node_descendants = map f m
111 instance Ord k => Foldable (Node k) where
112 foldMap f Node{node_value=Strict.Nothing, node_descendants=TreeMap m} =
113 foldMap (foldMap f) m
114 foldMap f Node{node_value=Strict.Just x, node_descendants=TreeMap m} =
115 f x `mappend` foldMap (foldMap f) m
116 instance Ord k => Traversable (Node k) where
117 traverse f Node{node_value=Strict.Nothing, node_descendants=TreeMap m, node_size} =
118 Node node_size <$> pure Strict.Nothing <*> (TreeMap <$> traverse (traverse f) m)
119 traverse f Node{node_value=Strict.Just x, node_descendants=TreeMap m, node_size} =
120 Node node_size <$> (Strict.Just <$> f x) <*> (TreeMap <$> traverse (traverse f) m)
121 instance (Ord k, NFData k, NFData x) => NFData (Node k x) where
122 rnf (Node s v d) = rnf s `seq` rnf v `seq` rnf d
124 node :: Strict.Maybe x -> TreeMap k x -> Node k x
125 node node_value node_descendants =
129 size node_descendants +
130 Strict.maybe 0 (const 1) node_value
134 node_empty :: Node k x
135 node_empty = node Strict.Nothing empty
137 node_find :: Ord k => [k] -> Node k x -> Strict.Maybe (Node k x)
138 node_find [] n = Strict.Just n
139 node_find (k:ks) Node{node_descendants=TreeMap m} =
140 maybe Strict.Nothing (node_find ks) $
145 -- | Return the empty 'TreeMap'.
147 empty = TreeMap Map.empty
149 -- | Return a 'TreeMap' only mapping the given 'Path' to the given value.
150 singleton :: Ord k => Path k -> x -> TreeMap k x
151 singleton ks x = insert const ks x empty
153 -- | Return a 'Node' only containing the given value.
154 leaf :: x -> Node k x
155 leaf x = node (Strict.Just x) empty
157 -- | Return the given 'TreeMap' associating the given 'Path' with the given value,
158 -- merging values if the given 'TreeMap' already associates the given 'Path'
159 -- with a non-'Strict.Nothing' 'node_value'.
160 insert :: Ord k => (x -> x -> x) -> Path k -> x -> TreeMap k x -> TreeMap k x
161 insert merge (k:|[]) x (TreeMap m) =
163 Map.insertWith (\_ Node{..} -> node
164 (Strict.maybe (Strict.Just x) (Strict.Just . merge x) node_value)
167 insert merge (k:|k':ks) x (TreeMap m) =
169 Map.insertWith (\_ Node{..} -> node node_value $
170 insert merge (path k' ks) x node_descendants)
172 (node Strict.Nothing (insert merge (path k' ks) x empty))
175 -- | Return a 'TreeMap' associating for each tuple of the given list
176 -- the 'Path' to the value,
177 -- merging values of identical 'Path's (in respective order).
178 from_List :: Ord k => (x -> x -> x) -> [(Path k, x)] -> TreeMap k x
179 from_List merge = Data.List.foldl (\acc (p, x) -> insert merge p x acc) empty
181 -- | Return a 'TreeMap' associating for each key and value of the given 'Map'
182 -- the 'Path' to the value,
183 -- merging values of identical 'Path's (in respective order).
184 from_Map :: Ord k => (x -> x -> x) -> Map (Path k) x -> TreeMap k x
185 from_Map merge = Map.foldlWithKey (\acc p x -> insert merge p x acc) empty
189 -- | Return the 'Map' in the given 'TreeMap'.
190 nodes :: TreeMap k x -> Map k (Node k x)
191 nodes (TreeMap m) = m
193 -- | Return 'True' iif. the given 'TreeMap' is 'empty'.
194 null :: TreeMap k x -> Bool
195 null (TreeMap m) = Map.null m
197 -- | Return the number of non-'Strict.Nothing' 'node_value's in the given 'TreeMap'.
199 -- * Complexity: O(r) where r is the size of the root 'Map'.
200 size :: TreeMap k x -> Int
201 size = Map.foldr ((+) . node_size) 0 . nodes
205 -- | Return the value (if any) associated with the given 'Path'.
206 find :: Ord k => Path k -> TreeMap k x -> Strict.Maybe x
207 find (k:|[]) (TreeMap m) = maybe Strict.Nothing node_value $ Map.lookup k m
208 find (k:|k':ks) (TreeMap m) =
209 maybe Strict.Nothing (find (path k' ks) . node_descendants) $
212 -- | Return the values (if any) associated with the prefixes of the given 'Path' (included).
213 find_along :: Ord k => Path k -> TreeMap k x -> [x]
214 find_along p (TreeMap tm) =
217 go :: Ord k => [k] -> Map k (Node k x) -> [x]
220 case Map.lookup k m of
223 Strict.maybe id (:) (node_value nod) $
224 go ks $ nodes (node_descendants nod)
226 -- | Return the 'Node' (if any) associated with the given 'Path'.
227 find_node :: Ord k => Path k -> TreeMap k x -> Maybe (Node k x)
228 find_node (k:|[]) (TreeMap m) = Map.lookup k m
229 find_node (k:|k':ks) (TreeMap m) =
231 find_node (path k' ks) . node_descendants
235 -- | Return a 'TreeMap' associating the same 'Path's as both given 'TreeMap's,
236 -- merging values (in respective order) when a 'Path' leads
237 -- to a non-'Strict.Nothing' 'node_value' in both given 'TreeMap's.
238 union :: Ord k => (x -> x -> x) -> TreeMap k x -> TreeMap k x -> TreeMap k x
239 union merge (TreeMap tm0) (TreeMap tm1) =
242 (\Node{node_value=x0, node_descendants=m0}
243 Node{node_value=x1, node_descendants=m1} ->
244 node (Strict.maybe x1 (\x0' -> Strict.maybe (Strict.Just x0') (Strict.Just . merge x0') x1) x0)
248 -- | Return the 'union' of the given 'TreeMap's.
250 -- NOTE: use 'Data.List.foldl'' to reduce demand on the control-stack.
251 unions :: Ord k => (x -> x -> x) -> [TreeMap k x] -> TreeMap k x
252 unions merge = Data.List.foldl' (union merge) empty
254 -- foldl' :: (a -> b -> a) -> a -> [b] -> a
258 -- go z (x:xs) = z `seq` go (f z x) xs
262 -- | Return the given 'TreeMap' with each non-'Strict.Nothing' 'node_value'
263 -- mapped by the given function.
264 map :: Ord k => (x -> y) -> TreeMap k x -> TreeMap k y
268 (\n@Node{node_value=x, node_descendants=m} ->
269 n{ node_value = fmap f x
270 , node_descendants = map f m
274 -- | Return the given 'TreeMap' with each 'Path' section
275 -- and each non-'Strict.Nothing' 'node_value'
276 -- mapped by the given functions.
278 -- WARNING: the function mapping 'Path' sections must be monotonic,
279 -- like in 'Map.mapKeysMonotonic'.
280 map_monotonic :: (Ord k, Ord l) => (k -> l) -> (x -> y) -> TreeMap k x -> TreeMap l y
281 map_monotonic fk fx =
283 Map.mapKeysMonotonic fk .
285 (\n@Node{node_value=x, node_descendants=m} ->
286 n{ node_value = fmap fx x
287 , node_descendants = map_monotonic fk fx m
291 -- | Return the given 'TreeMap' with each 'node_value'
292 -- mapped by the given function supplied with
293 -- the already mapped 'node_descendants' of the current 'Node'.
294 map_by_depth_first :: Ord k => (TreeMap k y -> Strict.Maybe x -> y) -> TreeMap k x -> TreeMap k y
295 map_by_depth_first f =
298 (\Node{node_value, node_descendants} ->
299 let m = map_by_depth_first f node_descendants in
300 node (Strict.Just $ f m node_value) m) .
305 alterl_path :: Ord k => (Strict.Maybe x -> Strict.Maybe x) -> Path k -> TreeMap k x -> TreeMap k x
310 => (Strict.Maybe x -> Strict.Maybe x) -> [k]
311 -> TreeMap k x -> TreeMap k x
313 go f (k:p) (TreeMap m) =
319 Just Node{node_value=v, node_descendants=d} -> (v, d)
320 Nothing -> (Strict.Nothing, empty) in
322 let gm = go f p cm in
323 case (fx, size gm) of
324 (Strict.Nothing, 0) -> Nothing
328 , node_descendants = gm
335 -- | Return the given accumulator folded by the given function
336 -- applied on non-'Strict.Nothing' 'node_value's
337 -- from left to right through the given 'TreeMap'.
338 foldl_with_Path :: Ord k => (a -> Path k -> x -> a) -> a -> TreeMap k x -> a
343 => [k] -> (a -> Path k -> x -> a)
344 -> a -> TreeMap k x -> a
345 foldp p fct a (TreeMap m) =
348 let acc' = Strict.maybe acc (fct acc (reverse $ path k p)) node_value in
349 foldp (k:p) fct acc' node_descendants) a m
351 -- | Return the given accumulator folded by the given function
352 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
353 -- from left to right through the given 'TreeMap'.
354 foldl_with_Path_and_Node :: Ord k => (a -> Node k x -> Path k -> x -> a) -> a -> TreeMap k x -> a
355 foldl_with_Path_and_Node =
359 => [k] -> (a -> Node k x -> Path k -> x -> a)
360 -> a -> TreeMap k x -> a
361 foldp p fct a (TreeMap m) =
363 (\acc k n@Node{..} ->
364 let acc' = Strict.maybe acc (fct acc n (reverse $ path k p)) node_value in
365 foldp (k:p) fct acc' node_descendants) a m
367 -- | Return the given accumulator folded by the given function
368 -- applied on non-'Strict.Nothing' 'node_value's
369 -- from right to left through the given 'TreeMap'.
370 foldr_with_Path :: Ord k => (Path k -> x -> a -> a) -> a -> TreeMap k x -> a
375 => [k] -> (Path k -> x -> a -> a)
376 -> a -> TreeMap k x -> a
377 foldp p fct a (TreeMap m) =
380 let acc' = foldp (k:p) fct acc node_descendants in
381 Strict.maybe acc' (\x -> fct (reverse $ path k p) x acc') node_value) a m
383 -- | Return the given accumulator folded by the given function
384 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
385 -- from right to left through the given 'TreeMap'.
386 foldr_with_Path_and_Node :: Ord k => (Node k x -> Path k -> x -> a -> a) -> a -> TreeMap k x -> a
387 foldr_with_Path_and_Node =
391 => [k] -> (Node k x -> Path k -> x -> a -> a)
392 -> a -> TreeMap k x -> a
393 foldp p fct a (TreeMap m) =
395 (\k n@Node{..} acc ->
396 let acc' = foldp (k:p) fct acc node_descendants in
397 Strict.maybe acc' (\x -> fct n (reverse $ path k p) x acc') node_value) a m
399 -- | Return the given accumulator folded by the given function
400 -- applied on non-'Strict.Nothing' 'node_value's
401 -- from left to right along the given 'Path'.
402 foldl_path :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
407 => (Path k -> x -> a -> a) -> [k] -> [k]
408 -> TreeMap k x -> a -> a
410 go f p (k:n) (TreeMap t) a =
411 case Map.lookup k t of
415 Strict.Nothing -> go f (k:p) n node_descendants a
416 Strict.Just x -> go f (k:p) n node_descendants (f (reverse $ path k p) x a)
418 -- | Return the given accumulator folded by the given function
419 -- applied on non-'Strict.Nothing' 'node_value's
420 -- from right to left along the given 'Path'.
421 foldr_path :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
426 => (Path k -> x -> a -> a) -> [k] -> [k]
427 -> TreeMap k x -> a -> a
429 go f p (k:n) (TreeMap t) a =
430 case Map.lookup k t of
434 Strict.Nothing -> go f (k:p) n node_descendants a
435 Strict.Just x -> f (reverse $ path k p) x $ go f (k:p) n node_descendants a
439 -- | Return a 'Map' associating each 'Path'
440 -- leading to a non-'Strict.Nothing' 'node_value' in the given 'TreeMap',
441 -- with its value mapped by the given function.
442 flatten :: Ord k => (x -> y) -> TreeMap k x -> Map (Path k) y
443 flatten = flatten_with_Path . const
445 -- | Like 'flatten' but with also the current 'Path' given to the mapping function.
446 flatten_with_Path :: Ord k => (Path k -> x -> y) -> TreeMap k x -> Map (Path k) y
451 => [k] -> (Path k -> x -> y)
454 flat_map p f (TreeMap m) =
456 Map.mapKeysMonotonic (reverse . flip path p) (
457 Map.mapMaybeWithKey (\k Node{node_value} ->
459 Strict.Nothing -> Nothing
460 Strict.Just x -> Just $ f (reverse $ path k p) x) m
463 (\k -> (:) . flat_map (k:p) f . node_descendants)
468 -- | Return the given 'TreeMap'
469 -- keeping only its non-'Strict.Nothing' 'node_value's
470 -- passing the given predicate.
471 filter :: Ord k => (x -> Bool) -> TreeMap k x -> TreeMap k x
474 (\_p x -> if f x then Strict.Just x else Strict.Nothing)
476 -- | Like 'filter' but with also the current 'Path' given to the predicate.
477 filter_with_Path :: Ord k => (Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
480 (\p x -> if f p x then Strict.Just x else Strict.Nothing)
482 -- | Like 'filter_with_Path' but with also the current 'Node' given to the predicate.
483 filter_with_Path_and_Node :: Ord k => (Node k x -> Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
484 filter_with_Path_and_Node f =
485 map_Maybe_with_Path_and_Node
486 (\n p x -> if f n p x then Strict.Just x else Strict.Nothing)
488 -- | Return the given 'TreeMap'
489 -- mapping its non-'Strict.Nothing' 'node_value's
490 -- and keeping only the non-'Strict.Nothing' results.
491 map_Maybe :: Ord k => (x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
492 map_Maybe = map_Maybe_with_Path . const
494 -- | Like 'map_Maybe' but with also the current 'Path' given to the predicate.
495 map_Maybe_with_Path :: Ord k => (Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
496 map_Maybe_with_Path = map_Maybe_with_Path_and_Node . const
498 -- | Like 'map_Maybe_with_Path' but with also the current 'Node' given to the predicate.
499 map_Maybe_with_Path_and_Node :: Ord k => (Node k x -> Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
500 map_Maybe_with_Path_and_Node =
504 => [k] -> (Node k x -> Path k -> x -> Strict.Maybe y)
507 go p test (TreeMap m) =
510 (\k nod@Node{node_value=v, node_descendants=ns} ->
511 let node_descendants = go (k:p) test ns in
512 let node_size = size node_descendants in
515 let node_value = test nod (reverse $ path k p) x in
517 Strict.Nothing | null node_descendants -> Nothing
518 Strict.Nothing -> Just Node{node_value, node_descendants, node_size=1 + node_size}
519 Strict.Just _ -> Just Node{node_value, node_descendants, node_size}
521 if null node_descendants
523 else Just Node{node_value=Strict.Nothing, node_descendants, node_size}