1 module Data.TreeSeq.Strict.Zipper where
3 import Control.Arrow (Kleisli(..))
4 import Control.Applicative (Applicative(..), Alternative(..))
5 import Control.Monad (Monad(..), (>=>))
8 import Data.Function (($), (.))
9 import Data.Functor ((<$>))
11 import Data.List.NonEmpty (NonEmpty(..))
12 import Data.Maybe (Maybe(..), maybe, mapMaybe)
13 import Data.Monoid (Monoid(..))
14 import Data.Semigroup (Semigroup(..))
15 import Data.Sequence (ViewL(..), ViewR(..), (<|), (|>))
16 import Data.Typeable (Typeable)
17 import Prelude (undefined)
18 import Text.Show (Show(..))
19 import qualified Data.List as List
20 import qualified Data.List.NonEmpty as NonEmpty
21 import qualified Data.Sequence as Seq
23 import Data.TreeSeq.Strict (Trees, Tree(..))
26 type Zipper k a = NonEmpty (Cursor k a)
28 -- | Return a 'Zipper' starting at the given 'Tree'.
29 zipper :: Tree k a -> Zipper k a
30 zipper t = Cursor mempty t mempty :| []
32 -- | Return a 'Zipper' starting at the left-most 'Tree' of the given 'Trees'.
33 zippers :: Trees k a -> [Zipper k a]
37 l :< ls -> pure $ Cursor mempty l ls :| []
39 -- | Return the 'Cursor' after zipping the given 'Zipper' upto its last parent.
40 root :: Zipper k a -> Cursor k a
41 root = NonEmpty.head . List.last . axis_ancestor_or_self
43 -- | Return the keys within the 'TreeN' nodes
44 -- leading to the current 'Cursor' of the given 'Zipper'.
45 path :: Zipper k x -> [k]
48 NonEmpty.toList cs >>= \c ->
53 -- | Return the 'Tree' currently under the 'Cursor'.
54 current :: Zipper k a -> Tree k a
55 current (Cursor _ t _ :| _) = t
57 -- | Return the 'Tree's selected by the given 'Axis' from the given 'Zipper'.
58 select :: Axis k a -> Zipper k a -> [Tree k a]
59 select axis c = cursor_self . NonEmpty.head <$> axis c
61 -- | Return the filtered values selected by the given 'Axis' from the given 'Zipper'.
62 filter :: Axis k a -> (Zipper k a -> Maybe b) -> Zipper k a -> [b]
63 filter axis f c = f `mapMaybe` axis c
68 { cursor_precedings :: Trees k a
69 , cursor_self :: Tree k a
70 , cursor_followings :: Trees k a
71 } deriving (Eq, Show, Typeable)
74 type Axis k a = Zipper k a -> [Zipper k a]
76 -- ** Type 'KleisliAxis'
77 type KleisliAxis k a = Kleisli [] (Zipper k a) (Zipper k a)
80 -- | Like 'Axis', but generalized with 'Alternative'.
82 -- Useful to return a 'Maybe' instead of a list.
83 type AxisAlt f k a = Zipper k a -> f (Zipper k a)
86 -- | Collect all 'Zipper's along a given axis,
87 -- including the first 'Zipper'.
88 axis_repeat :: AxisAlt Maybe k a -> Axis k a
89 axis_repeat f c = c : maybe [] (axis_repeat f) (f c)
91 -- | Collect all 'Zipper's along a given axis,
92 -- excluding the starting 'Zipper'.
93 axis_repeat_without_self :: AxisAlt Maybe k a -> Axis k a
94 axis_repeat_without_self f c = maybe [] (axis_repeat f) (f c)
97 axis_filter :: Axis k a -> (Zipper k a -> Bool) -> Axis k a
98 axis_filter axis f c = List.filter f (axis c)
99 infixl 5 `axis_filter`
102 axis_at :: Alternative f => Axis k a -> Int -> AxisAlt f k a
104 case List.drop i $ axis c of
110 axis_self :: Applicative f => AxisAlt f k a
114 axis_child :: Axis k a
116 axis_child_first c >>=
117 axis_repeat axis_following1
119 axis_child_lookup_first :: Alternative f => (k -> Bool) -> AxisAlt f k a
120 axis_child_lookup_first fk c = listHead $ axis_child_lookup fk c
122 axis_child_lookup :: (k -> Bool) -> Axis k a
123 axis_child_lookup fk cs@(Cursor _ps t _fs :| _) =
124 (<$> Seq.findIndicesL flt ns) $ \i ->
125 let (ps, ps') = Seq.splitAt i ns in
126 case Seq.viewl ps' of
128 l :< ls -> Cursor ps l ls :| NonEmpty.toList cs
131 flt (TreeN k _) = fk k
134 axis_child_first :: Alternative f => AxisAlt f k a
135 axis_child_first cs@(Cursor _ps t _fs :| _) =
136 case Seq.viewl $ nodesTree t of
138 l :< ls -> pure $ Cursor mempty l ls :| NonEmpty.toList cs
140 axis_child_last :: Alternative f => AxisAlt f k a
141 axis_child_last cs@(Cursor _ps t _fs :| _) =
142 case Seq.viewr $ nodesTree t of
144 rs :> r -> pure $ Cursor rs r mempty :| NonEmpty.toList cs
146 -- ** Axis @ancestor@
147 axis_ancestor :: Axis k a
148 axis_ancestor = axis_repeat_without_self axis_parent
150 axis_ancestor_or_self :: Axis k a
151 axis_ancestor_or_self = axis_repeat axis_parent
153 axis_root :: Alternative f => AxisAlt f k a
154 axis_root = pure . List.last . axis_ancestor_or_self
156 -- ** Axis @descendant@
157 axis_descendant_or_self :: Axis k a
158 axis_descendant_or_self =
161 collect_child acc c =
163 (collect_following_first acc)
165 collect_following_first acc c =
168 (collect_following_first acc)
172 axis_descendant_or_self_reverse :: Axis k a
173 axis_descendant_or_self_reverse c =
176 axis_descendant_or_self_reverse
177 (List.reverse $ axis_child c)
179 axis_descendant :: Axis k a
180 axis_descendant = List.tail . axis_descendant_or_self
182 -- ** Axis @preceding@
183 axis_preceding1 :: Alternative f => AxisAlt f k a
184 axis_preceding1 (Cursor ps t fs :| cs) =
187 rs :> r -> pure $ Cursor rs r (t <| fs) :| cs
189 axis_preceding_sibling :: Axis k a
190 axis_preceding_sibling = axis_repeat_without_self axis_preceding1
192 axis_preceding_sibling_first :: Alternative f => AxisAlt f k a
193 axis_preceding_sibling_first z@(Cursor ps t fs :| cs) =
194 case Seq.viewl (ps |> t) of
196 l :< ls -> pure $ Cursor mempty l (ls<>fs) :| cs
198 axis_preceding :: Axis k a
200 axis_ancestor_or_self >=>
201 axis_preceding_sibling >=>
202 axis_descendant_or_self_reverse
204 -- ** Axis @following@
205 axis_following1 :: Alternative f => AxisAlt f k a
206 axis_following1 (Cursor ps t fs :| cs) =
209 l :< ls -> pure $ Cursor (ps |> t) l ls :| cs
211 axis_following_sibling :: Axis k a
212 axis_following_sibling = axis_repeat_without_self axis_following1
214 axis_following_sibling_last :: Alternative f => AxisAlt f k a
215 axis_following_sibling_last z@(Cursor ps t fs :| cs) =
216 case Seq.viewr (t <| fs) of
218 rs :> r -> pure $ Cursor (ps<>rs) r mempty :| cs
220 axis_following :: Axis k a
222 axis_ancestor_or_self >=>
223 axis_following_sibling >=>
224 axis_descendant_or_self
227 axis_parent :: Alternative f => AxisAlt f k a
228 axis_parent (Cursor ps t fs :| cs) =
230 Cursor ps' (TreeN k _) fs' : cs' ->
231 pure $ Cursor ps' (TreeN k $ (ps |> t) <> fs) fs' :| cs'
235 nodesTree :: Tree k a -> Trees k a
236 nodesTree Tree0{} = mempty
237 nodesTree (TreeN _k ts) = ts
239 listHead :: Alternative f => [a] -> f a
241 listHead (a:_) = pure a