1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE NamedFieldPuns #-}
3 {-# OPTIONS_GHC -fno-warn-tabs #-}
5 module Data.TreeMap.Strict.Zipper where
7 import Control.Applicative (Applicative(..), Alternative(..))
8 import Control.Monad (Monad(..), (>=>))
9 import Data.Bool (Bool)
10 import Data.Data (Data)
12 import Data.Function (($), (.))
13 import Data.Functor ((<$>))
15 import Data.Maybe (Maybe(..), maybe)
16 import Data.NonNull (nuncons)
17 import Data.Ord (Ord(..))
18 import Data.Tuple (fst)
19 import Data.Typeable (Typeable)
20 import Text.Show (Show(..))
21 import qualified Data.List as List
22 import qualified Data.Map.Strict as Map
24 import Data.TreeMap.Strict (TreeMap(..), Node(..), Path)
25 import qualified Data.TreeMap.Strict as TreeMap
30 { zipper_path :: [Cursor k a]
31 , zipper_curr :: TreeMap k a
32 } deriving (Data, Eq, Show, Typeable)
34 zipper :: TreeMap k a -> Zipper k a
37 root :: Ord k => Zipper k a -> TreeMap k a
38 root = zipper_curr . List.last . axis_ancestor_or_self
40 zipath :: Zipper k a -> [k]
43 List.reverse (zipper_path z)
45 current :: Zipper k a -> TreeMap k a
51 { cursor_precedings :: TreeMap k a
52 , cursor_self :: (k, Node k a)
53 , cursor_followings :: TreeMap k a
54 } deriving (Data, Eq, Show, Typeable)
57 type Axis k a = Zipper k a -> [Zipper k a]
58 type AxisAlt f k a = Zipper k a -> f (Zipper k a)
60 -- | Collect all 'Zipper's along a given axis,
61 -- including the first 'Zipper'.
62 axis_collect :: (z -> Maybe z) -> z -> [z]
63 axis_collect f z = z : maybe [] (axis_collect f) (f z)
65 -- | Collect all 'Zipper's along a given axis,
66 -- excluding the first 'Zipper'.
67 axis_collect_without_self :: (z -> Maybe z) -> z -> [z]
68 axis_collect_without_self f z = maybe [] (axis_collect f) (f z)
71 axis_self :: Zipper k a -> Node k a
75 Cursor{cursor_self=(_, nod)}
77 _ -> TreeMap.nodeEmpty
80 axis_child :: Ord k => Axis k a
82 axis_child_first z >>=
83 axis_collect axis_following_sibling_nearest
86 :: (Ord k, Alternative f)
88 axis_child_lookup k (Zipper path (TreeMap m)) =
89 case Map.splitLookup k m of
90 (_, Nothing, _) -> empty
93 { zipper_path = Cursor (TreeMap ps) (k, s) (TreeMap fs) : path
94 , zipper_curr = TreeMap.node_descendants s
97 axis_child_lookups :: (Ord k, Alternative f, Monad f) => Path k -> AxisAlt f k a
98 axis_child_lookups p =
100 (k, Nothing) -> axis_child_lookup k
101 (k, Just p') -> axis_child_lookup k >=> axis_child_lookups p'
103 axis_child_first :: Alternative f => AxisAlt f k a
104 axis_child_first (Zipper path (TreeMap m)) =
105 case Map.minViewWithKey m of
107 Just ((k', s'), fs') ->
109 { zipper_path = Cursor TreeMap.empty (k', s') (TreeMap fs') : path
110 , zipper_curr = TreeMap.node_descendants s'
113 axis_child_last :: Alternative f => AxisAlt f k a
114 axis_child_last (Zipper path (TreeMap m)) =
115 case Map.maxViewWithKey m of
117 Just ((k', s'), ps') ->
119 { zipper_path = Cursor (TreeMap ps') (k', s') TreeMap.empty : path
120 , zipper_curr = TreeMap.node_descendants s'
123 -- ** Axis @ancestor@
124 axis_ancestor :: Ord k => Axis k a
125 axis_ancestor = axis_collect_without_self zipper_parent
127 axis_ancestor_or_self :: Ord k => Axis k a
128 axis_ancestor_or_self = axis_collect zipper_parent
130 -- ** Axis @descendant@
131 axis_descendant_or_self :: Ord k => Axis k a
132 axis_descendant_or_self =
135 collect_child acc z =
143 (axis_following_sibling_nearest z)
146 axis_descendant_or_self_reverse :: Ord k => Axis k a
147 axis_descendant_or_self_reverse z =
149 axis_descendant_or_self_reverse
150 (List.reverse $ axis_child z)
152 axis_descendant :: Ord k => Axis k a
153 axis_descendant = List.tail . axis_descendant_or_self
155 -- ** Axis @preceding@
156 axis_preceding_sibling_nearest :: (Ord k, Alternative f) => AxisAlt f k a
157 axis_preceding_sibling_nearest (Zipper path _curr) =
160 Cursor (TreeMap ps) (k, s) (TreeMap fs):steps ->
161 case Map.maxViewWithKey ps of
163 Just ((k', s'), ps') ->
165 { zipper_path = Cursor (TreeMap ps')
167 (TreeMap $ Map.insert k s fs)
169 , zipper_curr = TreeMap.node_descendants s'
172 axis_preceding_sibling :: Ord k => Axis k a
173 axis_preceding_sibling = axis_collect_without_self axis_preceding_sibling_nearest
175 axis_preceding :: Ord k => Axis k a
177 axis_ancestor_or_self >=>
178 axis_preceding_sibling >=>
179 axis_descendant_or_self_reverse
181 -- ** Axis @following@
182 axis_following_sibling_nearest :: (Ord k, Alternative f) => AxisAlt f k a
183 axis_following_sibling_nearest (Zipper path _curr) =
186 Cursor (TreeMap ps) (k, s) (TreeMap fs):steps ->
187 case Map.minViewWithKey fs of
189 Just ((k', s'), fs') ->
191 { zipper_path = Cursor (TreeMap $ Map.insert k s ps)
195 , zipper_curr = TreeMap.node_descendants s'
198 axis_following_sibling :: Ord k => Axis k a
199 axis_following_sibling = axis_collect_without_self axis_following_sibling_nearest
201 axis_following :: Ord k => Axis k a
203 axis_ancestor_or_self >=>
204 axis_following_sibling >=>
205 axis_descendant_or_self
208 zipper_parent :: (Ord k, Alternative f) => AxisAlt f k a
209 zipper_parent (Zipper path curr) =
212 Cursor (TreeMap ps) (k, s) (TreeMap fs):steps ->
213 let nod = TreeMap.node (TreeMap.node_value s) curr in
215 { zipper_path = steps
216 , zipper_curr = TreeMap $ Map.union ps $ Map.insert k nod fs
220 axis_filter :: (Axis k a) -> (Zipper k a -> Bool) -> (Axis k a)
221 axis_filter axis p z = List.filter p (axis z)
222 infixl 5 `axis_filter`
224 axis_at :: Alternative f => (Axis k a) -> Int -> (AxisAlt f k a)
225 axis_at axis n z = case List.drop n (axis z) of {[] -> empty; a:_ -> pure a}
228 zipper_null :: (Axis k a) -> Zipper k a -> Bool
229 zipper_null axis = List.null . axis