1 | module Control.Zipper
17 | Pointer : (i, a : Type) -> Type
18 | Pointer i a = (SnocList (i, a), List (i, a))
20 | fromPointer : i -> a -> Pointer i a -> List (i, a)
21 | fromPointer k x (l, r) = l <>> (k,x) :: r
36 | data ZipLayer : Type where
37 | (@>) : (i, a : Type) -> ZipLayer
41 | getTy : ZipLayer -> Type
47 | data Coil : List ZipLayer -> Type -> Type -> Type where
49 | Cons : Pointer j s -> j -> (List (i, a) -> s) ->
50 | Coil hs j s -> Coil (j @> s :: hs) i a
65 | data Zipper : List ZipLayer -> Type -> Type -> Type where
66 | MkZipper : Coil hs i a -> Pointer i a -> i -> a -> Zipper hs i a
71 | zipper : a -> Zipper [] () a
72 | zipper x = MkZipper Nil ([<], []) () x
76 | focus : IndexedLens' i (Zipper hs i a) a
77 | focus = ilens (\(MkZipper _ _ i x) => (i, x))
78 | (\(MkZipper coil p i _),x => MkZipper coil p i x)
88 | upward : Zipper (j @> s :: hs) i a -> Zipper hs j s
89 | upward (MkZipper (Cons p j k coil) q i x) =
90 | MkZipper coil p j $
k $
fromPointer i x q
97 | tug : (a -> Maybe a) -> a -> a
98 | tug f x = fromMaybe x (f x)
103 | rightward : Alternative f => Zipper hs i a -> f (Zipper hs i a)
104 | rightward (MkZipper _ (_, []) _ _) = empty
105 | rightward (MkZipper coil (l, (j,y) :: r) i x) =
106 | pure $
MkZipper coil (l :< (i,x), r) j y
111 | leftward : Alternative f => Zipper hs i a -> f (Zipper hs i a)
112 | leftward (MkZipper _ ([<], _) _ _) = empty
113 | leftward (MkZipper coil (l :< (j,y), r) i x) =
114 | pure $
MkZipper coil (l, (i,x) :: r) j y
118 | rightmost : Zipper hs i a -> Zipper hs i a
119 | rightmost (MkZipper coil (l,r) i x) =
120 | case l :< (i,x) <>< r of
121 | xs :< (j,y) => MkZipper coil (xs, []) j y
123 | [<] => assert_total $
idris_crash "Unreachable"
127 | leftmost : Zipper hs i a -> Zipper hs i a
128 | leftmost (MkZipper coil p i x) =
129 | case fromPointer i x p of
130 | (j,y) :: xs => MkZipper coil ([<], xs) j y
132 | [] => assert_total $
idris_crash "Unreachable"
139 | idownward : IndexedLens' i s a -> Zipper hs j s -> Zipper (j @> s :: hs) i a
140 | idownward l (MkZipper coil p j y) =
141 | let (i,x) = iview l y
142 | in MkZipper (Cons p j (go . map snd) coil) ([<],[]) i x
145 | go ls = set (partsOf l) ls y
151 | downward : Lens' s a -> Zipper hs j s -> Zipper (j @> s :: hs) () a
152 | downward l (MkZipper coil p i x) =
153 | MkZipper (Cons p i (go . map snd) coil) ([<], []) () (x ^. l)
156 | go ls = set (partsOf l) ls x
163 | iwithin : Alternative f => IndexedTraversal' i s a -> Zipper hs j s -> f (Zipper (j @> s :: hs) i a)
164 | iwithin l (MkZipper coil p j y) =
165 | case itoListOf l y of
166 | (i,x) :: xs => pure $
MkZipper (Cons p j (go . map snd) coil) ([<], xs) i x
170 | go ls = set (partsOf l) ls y
177 | within : Alternative f => Traversal' s a -> Zipper hs j s -> f (Zipper (j @> s :: hs) Nat a)
178 | within = iwithin . iordinal
181 | recoil : Coil hs i a -> List (i, a) -> getTy $
last (i @> a :: hs)
182 | recoil Nil xs = assert_total $
case xs of (_,x) :: _ => x
183 | recoil (Cons p i f coil) xs = recoil coil $
fromPointer i (f xs) p
187 | rezip : Zipper hs i a -> getTy $
last (i @> a :: hs)
188 | rezip (MkZipper coil p i x) = recoil coil $
fromPointer i x p