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 'NonNull' 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 Data.Map.Strict (Map)
24 import Data.Maybe (Maybe(..), maybe)
25 import Data.Monoid (Monoid(..))
26 import Data.NonNull (NonNull, nuncons, toNullable)
27 import Data.Ord (Ord(..))
28 import Data.Semigroup (Semigroup(..))
29 import Data.Sequences (reverse)
30 import Data.Traversable (Traversable(..))
31 import Data.Typeable (Typeable)
32 import Prelude (Int, Num(..), seq)
33 import Text.Show (Show(..))
34 import qualified Data.List as List
35 import qualified Data.Map.Strict as Map
36 import qualified Data.NonNull as NonNull
37 import qualified Data.Strict.Maybe as Strict
39 -- @Data.Strict@ orphan instances
40 deriving instance Data x => Data (Strict.Maybe x)
41 deriving instance Typeable Strict.Maybe
42 instance Semigroup x => Semigroup (Strict.Maybe x) where
43 Strict.Just x <> Strict.Just y = Strict.Just (x <> y)
44 x <> Strict.Nothing = x
45 Strict.Nothing <> y = y
46 instance Semigroup x => Monoid (Strict.Maybe x) where
47 mempty = Strict.Nothing
49 instance NFData x => NFData (Strict.Maybe x) where
50 rnf Strict.Nothing = ()
51 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 = 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.
76 type Path k = NonNull [k]
78 -- | 'Path' constructor.
79 path :: k -> [k] -> Path k
82 -- | Convenient alias.
83 (<|) :: k -> [k] -> Path k
89 { node_size :: !Int -- ^ The number of non-'Strict.Nothing' 'node_value's reachable from this 'Node'.
90 , node_value :: !(Strict.Maybe x) -- ^ Some value, or 'Strict.Nothing' if this 'Node' is intermediary.
91 , node_descendants :: !(TreeMap k x) -- ^ Descendants 'Node's.
92 } deriving (Data, Eq, Ord, Show, Typeable)
94 instance (Ord k, Semigroup v) => Semigroup (Node k v) where
96 Node{node_value=x0, node_descendants=m0}
97 Node{node_value=x1, node_descendants=m1} =
98 node (x0 <> x1) (union const m0 m1)
99 instance (Ord k, Semigroup v) => Monoid (Node k v) where
100 mempty = node Strict.Nothing (TreeMap mempty)
102 -- mconcat = List.foldr mappend mempty
103 instance Ord k => Functor (Node k) where
104 fmap f Node{node_value=x, node_descendants=m, node_size} =
106 { node_value = fmap f x
107 , node_descendants = map f m
110 instance Ord k => Foldable (Node k) where
111 foldMap f Node{node_value=Strict.Nothing, node_descendants=TreeMap m} =
112 foldMap (foldMap f) m
113 foldMap f Node{node_value=Strict.Just x, node_descendants=TreeMap m} =
114 f x `mappend` foldMap (foldMap f) m
115 instance Ord k => Traversable (Node k) where
116 traverse f Node{node_value=Strict.Nothing, node_descendants=TreeMap m, node_size} =
117 Node node_size <$> pure Strict.Nothing <*> (TreeMap <$> traverse (traverse f) m)
118 traverse f Node{node_value=Strict.Just x, node_descendants=TreeMap m, node_size} =
119 Node node_size <$> (Strict.Just <$> f x) <*> (TreeMap <$> traverse (traverse f) m)
120 instance (Ord k, NFData k, NFData x) => NFData (Node k x) where
121 rnf (Node s v d) = rnf s `seq` rnf v `seq` rnf d
123 node :: Strict.Maybe x -> TreeMap k x -> Node k x
124 node node_value node_descendants =
128 size node_descendants +
129 Strict.maybe 0 (const 1) node_value
133 nodeEmpty :: Node k x
134 nodeEmpty = node Strict.Nothing empty
136 nodeLookup :: Ord k => [k] -> Node k x -> Strict.Maybe (Node k x)
137 nodeLookup [] n = Strict.Just n
138 nodeLookup (k:ks) Node{node_descendants=TreeMap m} =
139 maybe Strict.Nothing (nodeLookup ks) $
144 -- | Return the empty 'TreeMap'.
146 empty = TreeMap Map.empty
148 -- | Return a 'TreeMap' only mapping the given 'Path' to the given value.
149 singleton :: Ord k => Path k -> x -> TreeMap k x
150 singleton ks x = insert const ks x empty
152 -- | Return a 'Node' only containing the given value.
153 leaf :: x -> Node k x
154 leaf x = node (Strict.Just x) empty
156 -- | Return the given 'TreeMap' associating the given 'Path' with the given value,
157 -- merging values if the given 'TreeMap' already associates the given 'Path'
158 -- with a non-'Strict.Nothing' 'node_value'.
159 insert :: Ord k => (x -> x -> x) -> Path k -> x -> TreeMap k x -> TreeMap k x
160 insert merge p x (TreeMap m) =
164 Map.insertWith (\_ Node{..} -> node
165 (Strict.maybe (Strict.Just x) (Strict.Just . merge x) node_value)
169 Map.insertWith (\_ Node{..} -> node node_value $
170 insert merge p' x node_descendants)
171 k (node Strict.Nothing (insert merge p' x empty)) m
173 -- | Return a 'TreeMap' associating for each tuple of the given list
174 -- the 'Path' to the value,
175 -- merging values of identical 'Path's (in respective order).
176 fromList :: Ord k => (x -> x -> x) -> [(Path k, x)] -> TreeMap k x
177 fromList merge = List.foldl (\acc (p, x) -> insert merge p x acc) empty
179 -- | Return a 'TreeMap' associating for each key and value of the given 'Map'
180 -- the 'Path' to the value,
181 -- merging values of identical 'Path's (in respective order).
182 fromMap :: Ord k => (x -> x -> x) -> Map (Path k) x -> TreeMap k x
183 fromMap merge = Map.foldlWithKey (\acc p x -> insert merge p x acc) empty
187 -- | Return the 'Map' in the given 'TreeMap'.
188 nodes :: TreeMap k x -> Map k (Node k x)
189 nodes (TreeMap m) = m
191 -- | Return 'True' iif. the given 'TreeMap' is 'empty'.
192 null :: TreeMap k x -> Bool
193 null (TreeMap m) = Map.null m
195 -- | Return the number of non-'Strict.Nothing' 'node_value's in the given 'TreeMap'.
197 -- * Complexity: O(r) where r is the size of the root 'Map'.
198 size :: TreeMap k x -> Int
199 size = Map.foldr ((+) . node_size) 0 . nodes
203 -- | Return the value (if any) associated with the given 'Path'.
204 lookup :: Ord k => Path k -> TreeMap k x -> Strict.Maybe x
205 lookup p (TreeMap m) =
206 maybe Strict.Nothing nod_val $ Map.lookup k m
211 Nothing -> node_value
212 Just p' -> lookup p' . node_descendants
214 -- | Return the values (if any) associated with the prefixes of the given 'Path' (included).
215 lookupAlong :: Ord k => Path k -> TreeMap k x -> [x]
216 lookupAlong p (TreeMap tm) =
219 go :: Ord k => [k] -> Map k (Node k x) -> [x]
222 case Map.lookup k m of
225 Strict.maybe id (:) (node_value nod) $
226 go ks $ nodes (node_descendants nod)
228 -- | Return the 'Node' (if any) associated with the given 'Path'.
229 lookupNode :: Ord k => Path k -> TreeMap k x -> Maybe (Node k x)
230 lookupNode p (TreeMap m) =
232 (k, Nothing) -> Map.lookup k m
233 (k, Just p') -> Map.lookup k m >>= lookupNode p' . node_descendants
237 -- | Return a 'TreeMap' associating the same 'Path's as both given 'TreeMap's,
238 -- merging values (in respective order) when a 'Path' leads
239 -- to a non-'Strict.Nothing' 'node_value' in both given 'TreeMap's.
240 union :: Ord k => (x -> x -> x) -> TreeMap k x -> TreeMap k x -> TreeMap k x
241 union merge (TreeMap tm0) (TreeMap tm1) =
244 (\Node{node_value=x0, node_descendants=m0}
245 Node{node_value=x1, node_descendants=m1} ->
246 node (Strict.maybe x1 (\x0' -> Strict.maybe (Strict.Just x0') (Strict.Just . merge x0') x1) x0)
250 -- | Return the 'union' of the given 'TreeMap's.
252 -- NOTE: use |List.foldl'| to reduce demand on the control-stack.
253 unions :: Ord k => (x -> x -> x) -> [TreeMap k x] -> TreeMap k x
254 unions merge = List.foldl' (union merge) empty
256 -- foldl' :: (a -> b -> a) -> a -> [b] -> a
260 -- go z (x:xs) = z `seq` go (f z x) xs
264 -- | Return the given 'TreeMap' with each non-'Strict.Nothing' 'node_value'
265 -- mapped by the given function.
266 map :: Ord k => (x -> y) -> TreeMap k x -> TreeMap k y
270 (\n@Node{node_value=x, node_descendants=m} ->
271 n{ node_value = fmap f x
272 , node_descendants = map f m
276 -- | Return the given 'TreeMap' with each 'Path' section
277 -- and each non-'Strict.Nothing' 'node_value'
278 -- mapped by the given functions.
280 -- WARNING: the function mapping 'Path' sections must be monotonic,
281 -- like in 'Map.mapKeysMonotonic'.
282 mapMonotonic :: (Ord k, Ord l) => (k -> l) -> (x -> y) -> TreeMap k x -> TreeMap l y
285 Map.mapKeysMonotonic fk .
287 (\n@Node{node_value=x, node_descendants=m} ->
288 n{ node_value = fmap fx x
289 , node_descendants = mapMonotonic fk fx m
293 -- | Return the given 'TreeMap' with each 'node_value'
294 -- mapped by the given function supplied with
295 -- the already mapped 'node_descendants' of the current 'Node'.
296 mapByDepthFirst :: Ord k => (TreeMap k y -> Strict.Maybe x -> y) -> TreeMap k x -> TreeMap k y
300 (\Node{node_value, node_descendants} ->
301 let m = mapByDepthFirst f node_descendants in
302 node (Strict.Just $ f m node_value) m) .
307 alterl_path :: Ord k => (Strict.Maybe x -> Strict.Maybe x) -> Path k -> TreeMap k x -> TreeMap k x
312 => (Strict.Maybe x -> Strict.Maybe x) -> [k]
313 -> TreeMap k x -> TreeMap k x
315 go f (k:p) (TreeMap m) =
321 Just Node{node_value=v, node_descendants=d} -> (v, d)
322 Nothing -> (Strict.Nothing, empty) in
324 let gm = go f p cm in
325 case (fx, size gm) of
326 (Strict.Nothing, 0) -> Nothing
330 , node_descendants = gm
337 -- | Return the given accumulator folded by the given function
338 -- applied on non-'Strict.Nothing' 'node_value's
339 -- from left to right through the given 'TreeMap'.
340 foldlWithPath :: Ord k => (a -> Path k -> x -> a) -> a -> TreeMap k x -> a
345 => [k] -> (a -> Path k -> x -> a)
346 -> a -> TreeMap k x -> a
347 foldp p fct a (TreeMap m) =
350 let acc' = Strict.maybe acc (fct acc (reverse $ path k p)) node_value in
351 foldp (k:p) fct acc' node_descendants) a m
353 -- | Return the given accumulator folded by the given function
354 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
355 -- from left to right through the given 'TreeMap'.
356 foldlWithPathAndNode :: Ord k => (a -> Node k x -> Path k -> x -> a) -> a -> TreeMap k x -> a
357 foldlWithPathAndNode =
361 => [k] -> (a -> Node k x -> Path k -> x -> a)
362 -> a -> TreeMap k x -> a
363 foldp p fct a (TreeMap m) =
365 (\acc k n@Node{..} ->
366 let acc' = Strict.maybe acc (fct acc n (reverse $ path k p)) node_value in
367 foldp (k:p) fct acc' node_descendants) a m
369 -- | Return the given accumulator folded by the given function
370 -- applied on non-'Strict.Nothing' 'node_value's
371 -- from right to left through the given 'TreeMap'.
372 foldrWithPath :: Ord k => (Path k -> x -> a -> a) -> a -> TreeMap k x -> a
377 => [k] -> (Path k -> x -> a -> a)
378 -> a -> TreeMap k x -> a
379 foldp p fct a (TreeMap m) =
382 let acc' = foldp (k:p) fct acc node_descendants in
383 Strict.maybe acc' (\x -> fct (reverse $ path k p) x acc') node_value) a m
385 -- | Return the given accumulator folded by the given function
386 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
387 -- from right to left through the given 'TreeMap'.
388 foldrWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> a -> a) -> a -> TreeMap k x -> a
389 foldrWithPathAndNode =
393 => [k] -> (Node k x -> Path k -> x -> a -> a)
394 -> a -> TreeMap k x -> a
395 foldp p fct a (TreeMap m) =
397 (\k n@Node{..} acc ->
398 let acc' = foldp (k:p) fct acc node_descendants in
399 Strict.maybe acc' (\x -> fct n (reverse $ path k p) x acc') node_value) a m
401 -- | Return the given accumulator folded by the given function
402 -- applied on non-'Strict.Nothing' 'node_value's
403 -- from left to right along the given 'Path'.
404 foldlPath :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
406 go fct [] . toNullable
409 => (Path k -> x -> a -> a) -> [k] -> [k]
410 -> TreeMap k x -> a -> a
412 go f p (k:n) (TreeMap t) a =
413 case Map.lookup k t of
417 Strict.Nothing -> go f (k:p) n node_descendants a
418 Strict.Just x -> go f (k:p) n node_descendants (f (reverse $ path k p) x a)
420 -- | Return the given accumulator folded by the given function
421 -- applied on non-'Strict.Nothing' 'node_value's
422 -- from right to left along the given 'Path'.
423 foldrPath :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
425 go fct [] . toNullable
428 => (Path k -> x -> a -> a) -> [k] -> [k]
429 -> TreeMap k x -> a -> a
431 go f p (k:n) (TreeMap t) a =
432 case Map.lookup k t of
436 Strict.Nothing -> go f (k:p) n node_descendants a
437 Strict.Just x -> f (reverse $ path k p) x $ go f (k:p) n node_descendants a
441 -- | Return a 'Map' associating each 'Path'
442 -- leading to a non-'Strict.Nothing' 'node_value' in the given 'TreeMap',
443 -- with its value mapped by the given function.
444 flatten :: Ord k => (x -> y) -> TreeMap k x -> Map (Path k) y
445 flatten = flattenWithPath . const
447 -- | Like 'flatten' but with also the current 'Path' given to the mapping function.
448 flattenWithPath :: Ord k => (Path k -> x -> y) -> TreeMap k x -> Map (Path k) y
453 => [k] -> (Path k -> x -> y)
456 flat_map p f (TreeMap m) =
458 Map.mapKeysMonotonic (reverse . flip path p) (
459 Map.mapMaybeWithKey (\k Node{node_value} ->
461 Strict.Nothing -> Nothing
462 Strict.Just x -> Just $ f (reverse $ path k p) x) m
465 (\k -> (:) . flat_map (k:p) f . node_descendants)
470 -- | Return the given 'TreeMap'
471 -- keeping only its non-'Strict.Nothing' 'node_value's
472 -- passing the given predicate.
473 filter :: Ord k => (x -> Bool) -> TreeMap k x -> TreeMap k x
476 (\_p x -> if f x then Strict.Just x else Strict.Nothing)
478 -- | Like 'filter' but with also the current 'Path' given to the predicate.
479 filterWithPath :: Ord k => (Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
482 (\p x -> if f p x then Strict.Just x else Strict.Nothing)
484 -- | Like 'filterWithPath' but with also the current 'Node' given to the predicate.
485 filterWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
486 filterWithPathAndNode f =
487 mapMaybeWithPathAndNode
488 (\n p x -> if f n p x then Strict.Just x else Strict.Nothing)
490 -- | Return the given 'TreeMap'
491 -- mapping its non-'Strict.Nothing' 'node_value's
492 -- and keeping only the non-'Strict.Nothing' results.
493 mapMaybe :: Ord k => (x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
494 mapMaybe = mapMaybeWithPath . const
496 -- | Like 'mapMaybe' but with also the current 'Path' given to the predicate.
497 mapMaybeWithPath :: Ord k => (Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
498 mapMaybeWithPath = mapMaybeWithPathAndNode . const
500 -- | Like 'mapMaybeWithPath' but with also the current 'Node' given to the predicate.
501 mapMaybeWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
502 mapMaybeWithPathAndNode =
506 => [k] -> (Node k x -> Path k -> x -> Strict.Maybe y)
509 go p test (TreeMap m) =
512 (\k nod@Node{node_value=v, node_descendants=ns} ->
513 let node_descendants = go (k:p) test ns in
514 let node_size = size node_descendants in
517 let node_value = test nod (reverse $ path k p) x in
519 Strict.Nothing | null node_descendants -> Nothing
520 Strict.Nothing -> Just Node{node_value, node_descendants, node_size=1 + node_size}
521 Strict.Just _ -> Just Node{node_value, node_descendants, node_size}
523 if null node_descendants
525 else Just Node{node_value=Strict.Nothing, node_descendants, node_size}