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_following_first
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 @descendant@
154 axis_descendant_or_self :: Axis k a
155 axis_descendant_or_self =
158 collect_child acc c =
160 (collect_following_first acc)
162 collect_following_first acc c =
165 (collect_following_first acc)
166 (axis_following_first c)
169 axis_descendant_or_self_reverse :: Axis k a
170 axis_descendant_or_self_reverse c =
173 axis_descendant_or_self_reverse
174 (List.reverse $ axis_child c)
176 axis_descendant :: Axis k a
177 axis_descendant = List.tail . axis_descendant_or_self
179 -- ** Axis @preceding@
180 axis_preceding_first :: Alternative f => AxisAlt f k a
181 axis_preceding_first (Cursor ps t fs :| cs) =
184 rs :> r -> pure $ Cursor rs r (t <| fs) :| cs
186 axis_preceding_sibling :: Axis k a
187 axis_preceding_sibling = axis_repeat_without_self axis_preceding_first
189 axis_preceding :: Axis k a
191 axis_ancestor_or_self >=>
192 axis_preceding_sibling >=>
193 axis_descendant_or_self_reverse
195 -- ** Axis @following@
196 axis_following_first :: Alternative f => AxisAlt f k a
197 axis_following_first (Cursor ps t fs :| cs) =
200 l :< ls -> pure $ Cursor (ps |> t) l ls :| cs
202 axis_following_sibling :: Axis k a
203 axis_following_sibling = axis_repeat_without_self axis_following_first
205 axis_following :: Axis k a
207 axis_ancestor_or_self >=>
208 axis_following_sibling >=>
209 axis_descendant_or_self
212 axis_parent :: Alternative f => AxisAlt f k a
213 axis_parent (Cursor ps t fs :| cs) =
215 Cursor ps' (TreeN k _) fs' : cs' ->
216 pure $ Cursor ps' (TreeN k $ (ps |> t) <> fs) fs' :| cs'
220 nodesTree :: Tree k a -> Trees k a
221 nodesTree Tree0{} = mempty
222 nodesTree (TreeN _k ts) = ts
224 listHead :: Alternative f => [a] -> f a
226 listHead (a:_) = pure a