16 | module Data.List.TailRec
18 | import Syntax.PreorderReasoning
19 | import Syntax.WithProof
26 | lengthAcc : List a -> Nat -> Nat
27 | lengthAcc [] acc = acc
28 | lengthAcc (_::xs) acc = lengthAcc xs $
S acc
31 | length : List a -> Nat
32 | length xs = lengthAcc xs Z
34 | lengthAccSucc : (xs : List a) -> (n : Nat) -> lengthAcc xs (S n) = S (lengthAcc xs n)
35 | lengthAccSucc [] _ = Refl
36 | lengthAccSucc (_::xs) n = rewrite lengthAccSucc xs (S n) in cong S Refl
39 | length_ext : (xs : List a) -> List.length xs = List.TailRec.length xs
40 | length_ext [] = Refl
41 | length_ext (_::xs) = rewrite length_ext xs in sym $
lengthAccSucc xs Z
43 | take_aux : Nat -> List a -> List a -> List a
44 | take_aux Z xs acc = reverseOnto [] acc
45 | take_aux (S n) [] acc = reverseOnto [] acc
46 | take_aux (S n) (x :: xs) acc = take_aux n xs (x :: acc)
49 | take : Nat -> List a -> List a
50 | take n xs = take_aux n xs []
54 | (n : Nat) -> (xs : List a) ->
55 | List.take n xs = List.TailRec.take n xs
56 | take_ext n xs = Calc $
58 | ~~ reverse [] ++ (List.take n xs) ...( Refl )
59 | ~~ reverseOnto (List.take n xs) [] ...( sym (revOnto (List.take n xs) []) )
60 | ~~ take_aux n xs [] ...( sym (lemma n xs []) )
62 | lemma : (n : Nat) -> (xs, acc : List a) ->
63 | take_aux n xs acc = reverseOnto (List.take n xs) acc
64 | lemma Z xs acc = Refl
65 | lemma (S n) [] acc = Refl
66 | lemma (S n) (x::xs) acc = lemma n xs (x :: acc)
69 | span_aux : (a -> Bool) -> List a -> List a -> (List a, List a)
70 | span_aux p [] acc = (reverseOnto [] acc, [])
71 | span_aux p (x::xs) acc =
73 | List.TailRec.span_aux p xs (x :: acc)
75 | (reverseOnto [] acc, x::xs)
78 | span : (a -> Bool) -> List a -> (List a, List a)
79 | span p xs = span_aux p xs []
81 | coe : (f : (i : a) -> Type) -> i = i' -> f i -> f i'
84 | span_aux_ext : (p : a -> Bool) -> (xs, acc : List a) ->
85 | (reverseOnto (fst $
List.span p xs) acc, snd $
List.span p xs)
88 | span_aux_ext p [] acc = Refl
90 | span_aux_ext p (x::xs) acc with (@@(p x), @@(List.span p xs))
91 | span_aux_ext p (x::xs) acc | ((
True ** px_tru)
, (
(pre, rest)**dl_pf)
) =
94 | let u = span_aux_ext p xs (x::acc) in
95 | coe (\u => (reverseOnto (x :: fst u) acc, snd u) =
96 | List.TailRec.span_aux p xs (x :: acc)) dl_pf u
97 | span_aux_ext p (x::xs) acc | ((
False**px_fls)
, (
(pre,rest)**dl_pf)
) =
102 | span_ext : (p : a -> Bool) -> (xs : List a) ->
103 | List.span p xs = List.TailRec.span p xs
104 | span_ext p xs with (@@(List.span p xs))
105 | span_ext p xs | (
(pre, rest) ** pf)
=
107 | let u = span_aux_ext p xs [] in
108 | coe (\u => (fst u, snd u) = span_aux p xs []) pf u
111 | break : (a -> Bool) -> List a -> (List a, List a)
112 | break p xs = List.TailRec.span (not . p) xs
115 | break_ext : (p : a -> Bool) -> (xs : List a) ->
116 | List.break p xs = List.TailRec.break p xs
117 | break_ext p xs = span_ext (not . p) xs
119 | splitOnto : List (List a) -> (a -> Bool) -> List a -> List1 (List a)
120 | splitOnto acc p xs =
121 | case List.break p xs of
122 | (chunk, [] ) => reverseOnto (chunk ::: []) acc
123 | (chunk, (c::rest)) => splitOnto (chunk::acc) p $
assert_smaller xs rest
126 | split : (a -> Bool) -> List a -> List1 (List a)
127 | split p xs = splitOnto [] p xs
129 | splitOnto_ext : (acc : List (List a)) -> (p : a -> Bool) -> (xs : List a) ->
130 | reverseOnto (List.split p xs) acc
131 | = List.TailRec.splitOnto acc p xs
132 | splitOnto_ext acc p xs with (@@(List.break p xs))
133 | splitOnto_ext acc p xs | (
(chunk, [] )**pf)
=
136 | splitOnto_ext acc p xs | (
(chunk, c::rest)**pf)
=
138 | rewrite splitOnto_ext (chunk::acc) p $
assert_smaller xs rest in
142 | split_ext : (p : a -> Bool) -> (xs : List a) ->
143 | List.split p xs = List.TailRec.split p xs
144 | split_ext p xs = splitOnto_ext [] p xs
147 | splitAtOnto : List a -> (n : Nat) -> (xs : List a) -> (List a, List a)
148 | splitAtOnto acc Z xs = (reverseOnto [] acc, xs)
149 | splitAtOnto acc (S n) [] = (reverseOnto [] acc, [])
150 | splitAtOnto acc (S n) (x::xs) = splitAtOnto (x::acc) n xs
153 | splitAt : (n : Nat) -> (xs : List a) -> (List a, List a)
154 | splitAt n xs = splitAtOnto [] n xs
156 | splitAtOnto_ext : (acc : List a) -> (n : Nat) -> (xs : List a) ->
157 | (reverseOnto (fst $
List.splitAt n xs) acc, snd $
List.splitAt n xs)
158 | = splitAtOnto acc n xs
159 | splitAtOnto_ext acc Z xs = Refl
160 | splitAtOnto_ext acc (S n) [] = Refl
161 | splitAtOnto_ext acc (S n) (x::xs) with (@@(List.splitAt n xs))
162 | splitAtOnto_ext acc (S n) (x::xs) | (
(tk, dr)**pf)
=
164 | let u = splitAtOnto_ext (x::acc) n xs in
165 | coe (\u => (reverseOnto (x :: fst u) acc, snd u) =
166 | splitAtOnto (x :: acc) n xs) pf u
169 | splitAt_ext : (n : Nat) -> (xs : List a) ->
170 | List.splitAt n xs =
171 | List.TailRec.splitAt n xs
172 | splitAt_ext n xs with (@@(List.splitAt n xs))
173 | splitAt_ext n xs | (
(tk, dr)**pf)
=
175 | rewrite sym $
splitAtOnto_ext [] n xs in
179 | partitionOnto : List a -> List a -> (a -> Bool) -> List a -> (List a, List a)
180 | partitionOnto lfts rgts p [] = (reverseOnto [] lfts, reverseOnto [] rgts)
181 | partitionOnto lfts rgts p (x::xs) =
183 | partitionOnto (x :: lfts) rgts p xs
185 | partitionOnto lfts (x::rgts) p xs
188 | partition : (a -> Bool) -> List a -> (List a, List a)
189 | partition p xs = partitionOnto [] [] p xs
191 | partitionOnto_ext : (lfts, rgts : List a) -> (p : a -> Bool) -> (xs : List a) ->
192 | (reverseOnto (fst $
List.partition p xs) lfts
193 | ,reverseOnto (snd $
List.partition p xs) rgts)
194 | = List.TailRec.partitionOnto lfts rgts p xs
195 | partitionOnto_ext lfts rgts p [] = Refl
196 | partitionOnto_ext lfts rgts p (x::xs) with (@@(p x), @@(List.partition p xs))
197 | partitionOnto_ext lfts rgts p (x::xs) | ((
True **px_tru)
, (
(dl_l, dl_r)**dl_pf)
)
198 | = rewrite px_tru in
201 | let u = partitionOnto_ext (x :: lfts) rgts p xs in
202 | coe (\u => (reverseOnto (x :: fst u) lfts
203 | ,reverseOnto ( snd u) rgts)
204 | = partitionOnto (x :: lfts) rgts p xs) dl_pf u
206 | partitionOnto_ext lfts rgts p (x::xs) | ((
False**px_fls)
, (
(dl_l, dl_r)**dl_pf)
)
207 | = rewrite px_fls in
210 | let u = partitionOnto_ext lfts (x :: rgts) p xs in
211 | coe (\u => (reverseOnto ( fst u) lfts
212 | ,reverseOnto (x :: snd u) rgts)
213 | = partitionOnto lfts (x::rgts) p xs) dl_pf u
215 | mergeReplicate_aux : a -> List a -> List a -> List a
216 | mergeReplicate_aux sep [] acc = reverseOnto [] acc
217 | mergeReplicate_aux sep (x::xs) acc = mergeReplicate_aux sep xs (x :: sep :: acc)
219 | mergeReplicate_ext : (sep : a) -> (xs : List a) -> (acc : List a) ->
220 | mergeReplicate_aux sep xs acc =
221 | reverseOnto (mergeReplicate sep xs) acc
222 | mergeReplicate_ext sep [] acc = Refl
223 | mergeReplicate_ext sep (x::xs) acc = Calc $
224 | |~ mergeReplicate_aux sep xs (x :: sep :: acc)
225 | ~~ reverseOnto (sep :: x :: mergeReplicate sep xs) acc
226 | ...( mergeReplicate_ext sep xs (x :: sep :: acc) )
229 | intersperse : a -> List a -> List a
230 | intersperse sep [] = []
231 | intersperse sep (y::ys) = y :: mergeReplicate_aux sep ys []
234 | intersperse_ext : (sep : a) -> (xs : List a) ->
235 | List.intersperse sep xs =
236 | List.TailRec.intersperse sep xs
237 | intersperse_ext sep [] = Refl
238 | intersperse_ext sep (y::ys) = cong (y::) (sym $
mergeReplicate_ext sep ys [])
240 | mapMaybeOnto : List b -> (a -> Maybe b) -> List a -> List b
241 | mapMaybeOnto acc f [] = reverseOnto [] acc
242 | mapMaybeOnto acc f (x::xs) =
244 | Nothing => mapMaybeOnto acc f xs
245 | Just y => mapMaybeOnto (y :: acc) f xs
248 | mapMaybe : (a -> Maybe b) -> List a -> List b
249 | mapMaybe f xs = mapMaybeOnto [] f xs
251 | mapMaybeOnto_ext : (acc : List b) -> (f : a -> Maybe b) -> (xs : List a) ->
252 | reverseOnto (List.mapMaybe f xs) acc
254 | mapMaybeOnto acc f xs
255 | mapMaybeOnto_ext acc f [] = Refl
256 | mapMaybeOnto_ext acc f (x::xs) with (f x)
257 | mapMaybeOnto_ext acc f (x::xs) | Nothing = mapMaybeOnto_ext acc f xs
258 | mapMaybeOnto_ext acc f (x::xs) | Just y = mapMaybeOnto_ext (y :: acc) f xs
261 | mapMaybe_ext : (f : a -> Maybe b) -> (xs : List a) ->
262 | List.mapMaybe f xs = List.TailRec.mapMaybe f xs
263 | mapMaybe_ext f xs = mapMaybeOnto_ext [] f xs
266 | sorted : Ord a => List a -> Bool
269 | sorted (x :: xs@(y :: ys)) = case (x <= y) of
271 | True => List.TailRec.sorted xs
275 | sorted_ext : Ord a => (xs : List a) ->
276 | List.sorted xs = List.TailRec.sorted xs
277 | sorted_ext [] = Refl
278 | sorted_ext [x] = Refl
279 | sorted_ext (x :: y :: ys) with (x <= y)
280 | sorted_ext (x :: y :: ys) | False = Refl
281 | sorted_ext (x :: y :: ys) | True = sorted_ext (y::ys)
283 | mergeByOnto : List a -> (a -> a -> Ordering) -> List a -> List a -> List a
284 | mergeByOnto acc order [] right = reverseOnto right acc
285 | mergeByOnto acc order left [] = reverseOnto left acc
286 | mergeByOnto acc order left@(x::xs) right@(y::ys) =
289 | LT => mergeByOnto (x :: acc) order (assert_smaller left xs) right
290 | _ => mergeByOnto (y :: acc) order left (assert_smaller right ys)
293 | mergeByOnto_ext : (acc : List a)
294 | -> (order : a -> a -> Ordering)
295 | -> (left, right : List a)
296 | -> reverseOnto (mergeBy order left right) acc
297 | = mergeByOnto acc order left right
298 | mergeByOnto_ext acc order [] right = Refl
299 | mergeByOnto_ext acc order left [] with( left)
300 | mergeByOnto_ext acc order _ [] | [] = Refl
301 | mergeByOnto_ext acc order _ [] | (_::_) = Refl
302 | mergeByOnto_ext acc order left@(x::xs) right@(y::ys) with (order x y)
303 | mergeByOnto_ext acc order left@(x::xs) right@(y::ys) | LT =
304 | mergeByOnto_ext (x :: acc) order xs (y::ys)
307 | mergeByOnto_ext acc order left@(x::xs) right@(y::ys) | EQ =
308 | mergeByOnto_ext (y :: acc) order (x::xs) ys
309 | mergeByOnto_ext acc order left@(x::xs) right@(y::ys) | GT =
310 | mergeByOnto_ext (y :: acc) order (x::xs) ys
313 | mergeBy : (a -> a -> Ordering) -> List a -> List a -> List a
314 | mergeBy order left right = mergeByOnto [] order left right
318 | mergeBy_ext : (order : a -> a -> Ordering) -> (left, right : List a) ->
319 | List.mergeBy order left right =
320 | List.TailRec.mergeBy order left right
321 | mergeBy_ext order left right = mergeByOnto_ext [] order left right
324 | merge : Ord a => List a -> List a -> List a
325 | merge = List.TailRec.mergeBy compare
329 | merge_ext : Ord a => (left, right : List a) ->
330 | List.merge left right = List.TailRec.merge left right
331 | merge_ext left right = mergeBy_ext compare left right
336 | sortBy_splitRec : List a -> List a -> (List a -> List a) -> (List a, List a)
337 | sortBy_splitRec (_::_::xs) (y::ys) zs = sortBy_splitRec xs ys (zs . ((::) y))
338 | sortBy_splitRec _ ys zs = (zs [], ys)
340 | sortBy_split : List a -> (List a, List a)
341 | sortBy_split xs = sortBy_splitRec xs xs id
344 | sortBy : (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
346 | sortBy cmp [x] = [x]
347 | sortBy cmp zs = let (xs, ys) = sortBy_split zs in
348 | List.TailRec.mergeBy cmp
349 | (List.TailRec.sortBy cmp (assert_smaller zs xs))
350 | (List.TailRec.sortBy cmp (assert_smaller zs ys))