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(..), Alternative((<|>)))
15 import Control.DeepSeq (NFData(..))
16 import Control.Monad (Monad(..))
18 import Data.Data (Data)
19 import Data.Eq (Eq(..))
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 Control.Applicative as App
35 import qualified Data.List as List
36 import qualified Data.Map.Strict as Map
37 import qualified Data.NonNull as NonNull
38 import qualified Data.Strict.Maybe as Strict
40 -- @Data.Strict@ orphan instances
41 deriving instance Data x => Data (Strict.Maybe x)
42 deriving instance Typeable Strict.Maybe
43 instance Semigroup x => Semigroup (Strict.Maybe x) where
44 Strict.Just x <> Strict.Just y = Strict.Just (x <> y)
45 x <> Strict.Nothing = x
46 Strict.Nothing <> y = y
47 instance Semigroup x => Monoid (Strict.Maybe x) where
48 mempty = Strict.Nothing
50 instance NFData x => NFData (Strict.Maybe x) where
51 rnf Strict.Nothing = ()
52 rnf (Strict.Just x) = rnf x
53 instance Applicative Strict.Maybe where
55 Strict.Just f <*> Strict.Just x = Strict.Just (f x)
56 _ <*> _ = Strict.Nothing
57 instance Alternative Strict.Maybe where
58 empty = Strict.Nothing
59 x <|> y = if Strict.isJust x then x else y
63 = TreeMap (Map k (Node k x))
64 deriving (Data, Eq, Ord, Show, Typeable)
66 instance (Ord k, Semigroup v) => Semigroup (TreeMap k v) where
68 instance (Ord k, Monoid v) => Monoid (TreeMap k v) where
70 mappend = union mappend
71 -- mconcat = List.foldr mappend mempty
72 instance Ord k => Functor (TreeMap k) where
73 fmap f (TreeMap m) = TreeMap $ fmap (fmap f) m
74 instance Ord k => Foldable (TreeMap k) where
75 foldMap f (TreeMap m) = foldMap (foldMap f) m
76 instance Ord k => Traversable (TreeMap k) where
77 traverse f (TreeMap m) = TreeMap <$> traverse (traverse f) m
78 instance (Ord k, NFData k, NFData x) => NFData (TreeMap k x) where
79 rnf (TreeMap m) = rnf m
82 -- | A 'Path' is a non-empty list of 'Map' keys.
83 type Path k = NonNull [k]
85 -- | 'Path' constructor.
86 path :: k -> [k] -> Path k
89 -- | Convenient alias.
90 (<|) :: k -> [k] -> Path k
96 { node_size :: !Int -- ^ The number of non-'Strict.Nothing' 'node_value's reachable from this 'Node'.
97 , node_value :: !(Strict.Maybe x) -- ^ Some value, or 'Strict.Nothing' if this 'Node' is intermediary.
98 , node_descendants :: !(TreeMap k x) -- ^ Descendants 'Node's.
99 } deriving (Data, Eq, Ord, Show, Typeable)
101 instance (Ord k, Semigroup v) => Semigroup (Node k v) where
103 Node{node_value=x0, node_descendants=m0}
104 Node{node_value=x1, node_descendants=m1} =
105 node (x0 <> x1) (union const m0 m1)
106 instance (Ord k, Semigroup v) => Monoid (Node k v) where
107 mempty = node Strict.Nothing (TreeMap mempty)
109 -- mconcat = List.foldr mappend mempty
110 instance Ord k => Functor (Node k) where
111 fmap f Node{node_value=x, node_descendants=m, node_size} =
113 { node_value = fmap f x
114 , node_descendants = map f m
117 instance Ord k => Foldable (Node k) where
118 foldMap f Node{node_value=Strict.Nothing, node_descendants=TreeMap m} =
119 foldMap (foldMap f) m
120 foldMap f Node{node_value=Strict.Just x, node_descendants=TreeMap m} =
121 f x `mappend` foldMap (foldMap f) m
122 instance Ord k => Traversable (Node k) where
123 traverse f Node{node_value=Strict.Nothing, node_descendants=TreeMap m, node_size} =
124 Node node_size <$> pure Strict.Nothing <*> (TreeMap <$> traverse (traverse f) m)
125 traverse f Node{node_value=Strict.Just x, node_descendants=TreeMap m, node_size} =
126 Node node_size <$> (Strict.Just <$> f x) <*> (TreeMap <$> traverse (traverse f) m)
127 instance (Ord k, NFData k, NFData x) => NFData (Node k x) where
128 rnf (Node s v d) = rnf s `seq` rnf v `seq` rnf d
130 node :: Strict.Maybe x -> TreeMap k x -> Node k x
131 node node_value node_descendants =
135 size node_descendants +
136 Strict.maybe 0 (const 1) node_value
140 nodeEmpty :: Node k x
141 nodeEmpty = node Strict.Nothing empty
143 nodeLookup :: Ord k => [k] -> Node k x -> Strict.Maybe (Node k x)
144 nodeLookup [] n = Strict.Just n
145 nodeLookup (k:ks) Node{node_descendants=TreeMap m} =
146 maybe Strict.Nothing (nodeLookup ks) $
151 -- | Return the empty 'TreeMap'.
153 empty = TreeMap Map.empty
155 -- | Return a 'TreeMap' only mapping the given 'Path' to the given value.
156 singleton :: Ord k => Path k -> x -> TreeMap k x
157 singleton ks x = insert const ks x empty
159 -- | Return a 'Node' only containing the given value.
160 leaf :: x -> Node k x
161 leaf x = node (Strict.Just x) empty
163 -- | Return the given 'TreeMap' associating the given 'Path' with the given value,
164 -- merging values if the given 'TreeMap' already associates the given 'Path'
165 -- with a non-'Strict.Nothing' 'node_value'.
166 insert :: Ord k => (x -> x -> x) -> Path k -> x -> TreeMap k x -> TreeMap k x
167 insert merge p x (TreeMap m) =
171 Map.insertWith (\_ Node{..} -> node
172 (Strict.maybe (Strict.Just x) (Strict.Just . merge x) node_value)
176 Map.insertWith (\_ Node{..} -> node node_value $
177 insert merge p' x node_descendants)
178 k (node Strict.Nothing (insert merge p' x empty)) m
180 -- | Return a 'TreeMap' from a list of 'Path'/value pairs,
181 -- with a combining function called on the leftest and rightest values
182 -- when their 'Path's are identical.
183 fromList :: Ord k => (x -> x -> x) -> [(Path k, x)] -> TreeMap k x
184 fromList merge = List.foldl' (\acc (p,x) -> insert merge p x acc) empty
186 -- | Return a 'TreeMap' from a 'Map' mapping 'Path' to value.
187 fromMap :: Ord k => Map (Path k) x -> TreeMap k x
188 fromMap = go . Map.toList
190 go :: Ord k => [(Path k,x)] -> TreeMap k x
192 TreeMap $ Map.fromAscListWith
193 (\Node{node_value=vn, node_descendants=mn}
194 Node{node_value=vo, node_descendants=mo} ->
195 node (vn <|> vo) $ union const mn mo) $
197 let (p0,mps) = nuncons p in
199 Nothing -> (p0,node (Strict.Just x) empty)
200 Just ps -> (p0,node Strict.Nothing $ go [(ps,x)])
201 -- fromMap = Map.foldlWithKey (\acc p x -> insert const p x acc) empty
205 -- | Return the 'Map' in the given 'TreeMap'.
206 nodes :: TreeMap k x -> Map k (Node k x)
207 nodes (TreeMap m) = m
209 -- | Return 'True' iif. the given 'TreeMap' is of 'size' @0@.
210 null :: TreeMap k x -> Bool
213 -- | Return the number of non-'Strict.Nothing' 'node_value's in the given 'TreeMap'.
215 -- * Complexity: O(r) where r is the size of the root 'Map'.
216 size :: TreeMap k x -> Int
217 size = Map.foldr ((+) . node_size) 0 . nodes
221 -- | Return the value (if any) associated with the given 'Path'.
222 lookup :: Ord k => Path k -> TreeMap k x -> Strict.Maybe x
223 lookup p (TreeMap m) =
224 maybe Strict.Nothing nod_val $ Map.lookup k m
229 Nothing -> node_value
230 Just p' -> lookup p' . node_descendants
232 -- | Return the values (if any) associated with the prefixes of the given 'Path' (included).
233 lookupAlong :: Ord k => Path k -> TreeMap k x -> [x]
234 lookupAlong p (TreeMap tm) =
237 go :: Ord k => [k] -> Map k (Node k x) -> [x]
240 case Map.lookup k m of
243 Strict.maybe id (:) (node_value nod) $
244 go ks $ nodes (node_descendants nod)
246 -- | Return the 'Node' (if any) associated with the given 'Path'.
247 lookupNode :: Ord k => Path k -> TreeMap k x -> Maybe (Node k x)
248 lookupNode p (TreeMap m) =
250 (k, Nothing) -> Map.lookup k m
251 (k, Just p') -> Map.lookup k m >>= lookupNode p' . node_descendants
255 -- | Return a 'TreeMap' associating the same 'Path's as both given 'TreeMap's,
256 -- merging values (in respective order) when a 'Path' leads
257 -- to a non-'Strict.Nothing' 'node_value' in both given 'TreeMap's.
258 union :: Ord k => (x -> x -> x) -> TreeMap k x -> TreeMap k x -> TreeMap k x
259 union merge (TreeMap tm0) (TreeMap tm1) =
262 (\Node{node_value=x0, node_descendants=m0}
263 Node{node_value=x1, node_descendants=m1} ->
264 node (Strict.maybe x1 (\x0' -> Strict.maybe (Strict.Just x0') (Strict.Just . merge x0') x1) x0)
268 -- | Return the 'union' of the given 'TreeMap's.
270 -- NOTE: use |List.foldl'| to reduce demand on the control-stack.
271 unions :: Ord k => (x -> x -> x) -> [TreeMap k x] -> TreeMap k x
272 unions merge = List.foldl' (union merge) empty
274 -- foldl' :: (a -> b -> a) -> a -> [b] -> a
278 -- go z (x:xs) = z `seq` go (f z x) xs
282 -- | Return the given 'TreeMap' with each non-'Strict.Nothing' 'node_value'
283 -- mapped by the given function.
284 map :: Ord k => (x -> y) -> TreeMap k x -> TreeMap k y
288 (\n@Node{node_value=x, node_descendants=m} ->
289 n{ node_value = fmap f x
290 , node_descendants = map f m
294 -- | Return the given 'TreeMap' with each 'Path' section
295 -- and each non-'Strict.Nothing' 'node_value'
296 -- mapped by the given functions.
298 -- WARNING: the function mapping 'Path' sections must be monotonic,
299 -- like in 'Map.mapKeysMonotonic'.
300 mapMonotonic :: (Ord k, Ord l) => (k -> l) -> (x -> y) -> TreeMap k x -> TreeMap l y
303 Map.mapKeysMonotonic fk .
305 (\n@Node{node_value=x, node_descendants=m} ->
306 n{ node_value = fmap fx x
307 , node_descendants = mapMonotonic fk fx m
311 -- | Return the given 'TreeMap' with each 'node_value'
312 -- mapped by the given function supplied with
313 -- the already mapped 'node_descendants' of the current 'Node'.
314 mapByDepthFirst :: Ord k => (TreeMap k y -> Strict.Maybe x -> y) -> TreeMap k x -> TreeMap k y
318 (\Node{node_value, node_descendants} ->
319 let m = mapByDepthFirst f node_descendants in
320 node (Strict.Just $ f m node_value) m) .
325 alterl_path :: Ord k => (Strict.Maybe x -> Strict.Maybe x) -> Path k -> TreeMap k x -> TreeMap k x
330 => (Strict.Maybe x -> Strict.Maybe x) -> [k]
331 -> TreeMap k x -> TreeMap k x
333 go f (k:p) (TreeMap m) =
339 Just Node{node_value=v, node_descendants=d} -> (v, d)
340 Nothing -> (Strict.Nothing, empty) in
342 let gm = go f p cm in
343 case (fx, size gm) of
344 (Strict.Nothing, 0) -> Nothing
348 , node_descendants = gm
355 -- | Return the given accumulator folded by the given function
356 -- applied on non-'Strict.Nothing' 'node_value's
357 -- from left to right through the given 'TreeMap'.
358 foldlWithPath :: Ord k => (a -> Path k -> x -> a) -> a -> TreeMap k x -> a
363 => [k] -> (a -> Path k -> x -> a)
364 -> a -> TreeMap k x -> a
365 foldp p fct a (TreeMap m) =
368 let acc' = Strict.maybe acc (fct acc (reverse $ path k p)) node_value in
369 foldp (k:p) fct acc' node_descendants) a m
371 -- | Return the given accumulator folded by the given function
372 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
373 -- from left to right through the given 'TreeMap'.
374 foldlWithPathAndNode :: Ord k => (a -> Node k x -> Path k -> x -> a) -> a -> TreeMap k x -> a
375 foldlWithPathAndNode =
379 => [k] -> (a -> Node k x -> Path k -> x -> a)
380 -> a -> TreeMap k x -> a
381 foldp p fct a (TreeMap m) =
383 (\acc k n@Node{..} ->
384 let acc' = Strict.maybe acc (fct acc n (reverse $ path k p)) node_value in
385 foldp (k:p) fct acc' node_descendants) a m
387 -- | Return the given accumulator folded by the given function
388 -- applied on non-'Strict.Nothing' 'node_value's
389 -- from right to left through the given 'TreeMap'.
390 foldrWithPath :: Ord k => (Path k -> x -> a -> a) -> a -> TreeMap k x -> a
395 => [k] -> (Path k -> x -> a -> a)
396 -> a -> TreeMap k x -> a
397 foldp p fct a (TreeMap m) =
400 let acc' = foldp (k:p) fct acc node_descendants in
401 Strict.maybe acc' (\x -> fct (reverse $ path k p) x acc') node_value) a m
403 -- | Return the given accumulator folded by the given function
404 -- applied on non-'Strict.Nothing' 'Node's and 'node_value's
405 -- from right to left through the given 'TreeMap'.
406 foldrWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> a -> a) -> a -> TreeMap k x -> a
407 foldrWithPathAndNode =
411 => [k] -> (Node k x -> Path k -> x -> a -> a)
412 -> a -> TreeMap k x -> a
413 foldp p fct a (TreeMap m) =
415 (\k n@Node{..} acc ->
416 let acc' = foldp (k:p) fct acc node_descendants in
417 Strict.maybe acc' (\x -> fct n (reverse $ path k p) x acc') node_value) a m
419 -- | Return the given accumulator folded by the given function
420 -- applied on non-'Strict.Nothing' 'node_value's
421 -- from left to right along the given 'Path'.
422 foldlPath :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
424 go fct [] . toNullable
427 => (Path k -> x -> a -> a) -> [k] -> [k]
428 -> TreeMap k x -> a -> a
430 go f p (k:n) (TreeMap t) a =
431 case Map.lookup k t of
435 Strict.Nothing -> go f (k:p) n node_descendants a
436 Strict.Just x -> go f (k:p) n node_descendants (f (reverse $ path k p) x a)
438 -- | Return the given accumulator folded by the given function
439 -- applied on non-'Strict.Nothing' 'node_value's
440 -- from right to left along the given 'Path'.
441 foldrPath :: Ord k => (Path k -> x -> a -> a) -> Path k -> TreeMap k x -> a -> a
443 go fct [] . toNullable
446 => (Path k -> x -> a -> a) -> [k] -> [k]
447 -> TreeMap k x -> a -> a
449 go f p (k:n) (TreeMap t) a =
450 case Map.lookup k t of
454 Strict.Nothing -> go f (k:p) n node_descendants a
455 Strict.Just x -> f (reverse $ path k p) x $ go f (k:p) n node_descendants a
459 -- | Return a 'Map' associating each 'Path'
460 -- leading to a non-'Strict.Nothing' 'node_value' in the given 'TreeMap',
461 -- with its value mapped by the given function.
462 flatten :: Ord k => (x -> y) -> TreeMap k x -> Map (Path k) y
463 flatten = flattenWithPath . const
465 -- | Like 'flatten' but with also the current 'Path' given to the mapping function.
466 flattenWithPath :: Ord k => (Path k -> x -> y) -> TreeMap k x -> Map (Path k) y
471 => [k] -> (Path k -> x -> y)
474 flat_map p f (TreeMap m) =
476 Map.mapKeysMonotonic (reverse . flip path p) (
477 Map.mapMaybeWithKey (\k Node{node_value} ->
479 Strict.Nothing -> Nothing
480 Strict.Just x -> Just $ f (reverse $ path k p) x) m
483 (\k -> (:) . flat_map (k:p) f . node_descendants)
488 -- | Return the given 'TreeMap'
489 -- keeping only its non-'Strict.Nothing' 'node_value's
490 -- passing the given predicate.
491 filter :: Ord k => (x -> Bool) -> TreeMap k x -> TreeMap k x
494 (\_p x -> if f x then Strict.Just x else Strict.Nothing)
496 -- | Like 'filter' but with also the current 'Path' given to the predicate.
497 filterWithPath :: Ord k => (Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
500 (\p x -> if f p x then Strict.Just x else Strict.Nothing)
502 -- | Like 'filterWithPath' but with also the current 'Node' given to the predicate.
503 filterWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> Bool) -> TreeMap k x -> TreeMap k x
504 filterWithPathAndNode f =
505 mapMaybeWithPathAndNode
506 (\n p x -> if f n p x then Strict.Just x else Strict.Nothing)
508 -- | Return the given 'TreeMap'
509 -- mapping its non-'Strict.Nothing' 'node_value's
510 -- and keeping only the non-'Strict.Nothing' results.
511 mapMaybe :: Ord k => (x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
512 mapMaybe = mapMaybeWithPath . const
514 -- | Like 'mapMaybe' but with also the current 'Path' given to the predicate.
515 mapMaybeWithPath :: Ord k => (Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
516 mapMaybeWithPath = mapMaybeWithPathAndNode . const
518 -- | Like 'mapMaybeWithPath' but with also the current 'Node' given to the predicate.
519 mapMaybeWithPathAndNode :: Ord k => (Node k x -> Path k -> x -> Strict.Maybe y) -> TreeMap k x -> TreeMap k y
520 mapMaybeWithPathAndNode =
524 => [k] -> (Node k x -> Path k -> x -> Strict.Maybe y)
527 go p test (TreeMap m) =
530 (\k nod@Node{node_value=v, node_descendants=ns} ->
531 let node_descendants = go (k:p) test ns in
532 let node_size = size node_descendants in
535 let node_value = test nod (reverse $ path k p) x in
537 Strict.Nothing | null node_descendants -> Nothing
538 Strict.Nothing -> Just Node{node_value, node_descendants, node_size=1 + node_size}
539 Strict.Just _ -> Just Node{node_value, node_descendants, node_size}
541 if null node_descendants
543 else Just Node{node_value=Strict.Nothing, node_descendants, node_size}
548 (\\) :: Ord k => TreeMap k x -> TreeMap k y -> TreeMap k x
549 (\\) = intersection const
553 (Strict.Maybe x -> Strict.Maybe y -> Strict.Maybe z) ->
554 TreeMap k x -> TreeMap k y -> TreeMap k z
555 intersection merge (TreeMap x) (TreeMap y) =
559 node (node_value xn `merge` node_value yn) $
561 (node_descendants xn)
562 (node_descendants yn))