(** This greatly seconds "TakeDrop" module, but for streams instead of lists *)
Set Implicit Arguments.
Require Coq.Arith.Le.
Require Import Coq.Lists.List.
Require Import Coq.Lists.Streams.
Require Beroal.Init.
Require Import Beroal.TakeDrop.
Section element.
Variable e : Type.
Definition drop_pres_eq : forall n (xs ys : Stream e),
EqSt xs ys -> EqSt (Str_nth_tl n xs) (Str_nth_tl n ys).
Proof.
refine (fix rec (n : nat) xs ys eq0 := _).
destruct n as [|pn].
simpl.
refine (eq0).
simpl.
destruct eq0 as [p0 p1].
refine (rec _ _ _ p1).
Qed.
Definition In (x : e) := Exists (fun xs => x = hd xs).
Definition non_dup := ForAll (fun xs => ~ In (hd xs) (tl xs)).
Definition filtered_finite (p : e -> Prop)
:= Exists (ForAll (fun ys => ~ p (hd ys))).
Definition filtered_infinite (p : e -> Prop)
:= ForAll (Exists (fun ys => p (hd ys))).
Definition app xs0 (ys : Stream e) := (cofix rec (xs : list e)
:= match xs with
| nil => ys
| List.cons x xss => Streams.Cons x (rec xss)
end) xs0.
Definition take := fix rec (n : nat) (xs : Stream e)
:= match n with
| O => nil
| S pn => List.cons (hd xs) (rec pn (tl xs))
end.
Definition take_pres_eq : forall xs ys,
EqSt xs ys -> forall n, take n xs = take n ys.
Proof.
refine (fix rec xs ys eq0 (n : nat) {struct n} := _).
destruct n as [|pn].
simpl.
refine (refl_equal _).
simpl.
destruct eq0 as [p0 p1].
refine (eq_ind _ (fun dep => _ = dep :: _) _ _ p0).
refine (f_equal _ (rec _ _ p1 _)).
Qed.
(** permuting take and tail *)
Check fun n xs => (refl_equal _) : take n (tl xs) = List.tail (take (S n) xs).
(** obvious simplifications *)
Check fun x xs ys => conj (refl_equal _)
(conj (refl_equal _)
(conj (refl_equal _)
(refl_equal _)))
: hd ys = hd (app nil ys)
/\ tl ys = tl (app nil ys)
/\ x = hd (app (x :: xs) ys)
/\ app xs ys = tl (app (x :: xs) ys).
Definition app_nil_id : forall xs, EqSt xs (app nil xs).
Proof.
refine (fun xs => eqst _ _ _ _).
refine (refl_equal _).
simpl.
refine (EqSt_reflex _).
Qed.
Definition app_comm_cons : forall x xs ys,
EqSt (Streams.Cons x (app xs ys)) (app (x :: xs) ys).
Proof.
refine (fun x xs ys => eqst _ _ _ _).
refine (refl_equal _).
refine (EqSt_reflex _).
Qed.
Definition app_single_cons : forall x xs,
EqSt (Streams.Cons x xs) (app (x :: nil) xs).
Proof.
refine (fun x xs => eqst _ _ _ _).
refine (refl_equal _).
refine (eqst _ _ _ _).
refine (refl_equal _).
refine (EqSt_reflex _).
Qed.
Definition app_pres_eq : forall xs ys, EqSt xs ys
-> forall zs, EqSt (app zs xs) (app zs ys).
Proof.
refine (fun xs ys eq0 => fix rec (zs : list e) := _).
destruct zs as [|z zss].
destruct eq0 as [eq1 eq2].
refine (eqst (app nil xs) (app nil ys) eq1 eq2).
refine (eqst _ _ _ _).
refine (refl_equal _).
refine (rec zss).
Qed.
Definition take_app_degen : forall n xs ys, n <= length xs
-> TakeDrop.take n xs = take n (app xs ys).
Proof.
refine (fix rec n (xs : list e) ys {struct xs} := _).
destruct xs as [|x xss].
simpl.
refine (fun le0 => _).
rewrite <- (Coq.Arith.Le.le_n_O_eq _ le0).
simpl.
refine (refl_equal _).
simpl.
destruct n as [|pn].
simpl.
refine (fun _ => refl_equal _).
refine (fun le0 => _).
refine (f_equal (List.cons x)
(rec _ _ _ (Coq.Arith.Le.le_S_n _ _ le0))).
Qed.
Definition drop_app_degen : forall n xs ys, n <= length xs
-> EqSt (app (TakeDrop.drop n xs) ys)
(Str_nth_tl n (app xs ys)).
Proof.
refine (fix rec n (xs : list e) ys {struct xs} := _).
destruct xs as [|x xss].
simpl.
refine (fun le0 => _).
rewrite <- (Coq.Arith.Le.le_n_O_eq _ le0).
simpl.
refine (EqSt_reflex _).
simpl.
destruct n as [|pn].
simpl.
refine (fun _ => EqSt_reflex _).
refine (fun le0 => _).
refine (rec _ _ _ (Coq.Arith.Le.le_S_n _ _ le0)).
Qed.
Definition take_app_part : forall n ys xs,
xs ++ (take n ys) = take (length xs + n) (app xs ys).
Proof.
refine (fun n ys => fix rec (xs : list e) := _).
destruct xs as [|x xss].
refine (take_pres_eq _ _).
refine (app_nil_id _).
refine (f_equal (List.cons x) (rec xss)).
Qed.
Definition drop_app_part : forall n ys xs,
EqSt (Str_nth_tl n ys)
(Str_nth_tl (length xs + n) (app xs ys)).
Proof.
refine (fun n ys => fix rec (xs : list e) := _).
destruct xs as [|x xss].
refine (drop_pres_eq _ _).
refine (app_nil_id _).
refine (rec xss).
Qed.
Definition take_app_exact : forall xs ys,
xs = take (length xs) (app xs ys).
Proof.
refine (fun xs ys => _).
refine (eq_ind _ (fun dep => _ = take dep _)
_ _ (Coq.Arith.Plus.plus_0_r _)).
refine (eq_ind _ (fun dep => dep = _)
_ _ (sym_eq (app_nil_end _))).
refine (take_app_part 0 _ _).
Qed.
Definition drop_app_exact : forall xs ys,
EqSt ys (Str_nth_tl (length xs) (app xs ys)).
Proof.
refine (fun xs ys => _).
refine (eq_ind _ (fun dep => EqSt _ (Str_nth_tl dep _))
_ _ (Coq.Arith.Plus.plus_0_r _)).
refine (drop_app_part 0 _ _).
Qed.
Definition take_app_drop : forall n xs,
EqSt xs (app (take n xs) (Str_nth_tl n xs)).
Proof.
refine (fix rec (n : nat) xs := _).
destruct n as [|pn].
simpl.
refine (app_nil_id _).
refine (eqst _ _ _ _).
simpl.
refine (refl_equal _).
refine (rec pn (tl xs)).
Qed.
Definition drop_plus : forall n m xs,
EqSt (Str_nth_tl n xs)
(app (take m (Str_nth_tl n xs)) (Str_nth_tl (n + m) xs)).
Proof.
refine (fix rec (n : nat) m xs {struct n} := _).
destruct n as [|pn].
simpl.
refine (take_app_drop _ _).
simpl.
refine (rec pn m (tl xs)).
Qed.
Definition take_plus : forall n m xs,
take (n + m) xs = take n xs ++ take m (Str_nth_tl n xs).
Proof.
refine (fix rec (n : nat) m xs {struct n} := _).
destruct n as [|pn].
simpl.
refine (refl_equal _).
simpl.
refine (f_equal _ (rec pn m (tl xs))).
Qed.
Definition iterate (f : e -> e) := cofix rec (x : e)
:= (Streams.Cons x (rec (f x))).
Definition cycle (x : e) (xs : list e)
:= cofix rec := Streams.Cons x (app xs rec).
Definition cyclic (period : nat) (xs : Stream e)
:= EqSt xs (Str_nth_tl period xs).
Definition repeat (x : e)
:= cofix rec := Streams.Cons x rec.
Definition replicate n (x : e) := take n (repeat x).
Definition iterate_id_cyclic : forall x n,
cyclic n (iterate (@Beroal.Init.id _) x).
Proof.
refine (fun x => _).
refine (fix rec (n : nat) := _).
destruct n as [|pn].
refine (EqSt_reflex _).
unfold cyclic.
refine (rec pn).
Qed.
Definition iterate_id_nth : forall x n,
x = Str_nth n (iterate (@Beroal.Init.id _) x).
Proof.
refine (fun x n => match iterate_id_cyclic x n with eqst p _ => p end).
Qed.
Definition cycle_single_cyclic : forall x n, cyclic n (cycle x nil).
Proof.
refine (fun x => _).
refine (fix rec (n : nat) := _).
destruct n as [|pn].
refine (EqSt_reflex _).
unfold cyclic.
simpl.
refine (trans_EqSt (rec pn) (drop_pres_eq _ (app_nil_id _))).
Qed.
Definition cycle_single_nth : forall x n,
x = Str_nth n (cycle x nil).
Proof.
refine (fun x n => match cycle_single_cyclic x n with eqst p _ => p end).
Qed.
Definition iterate_id_eq_cycle_single : forall x,
EqSt (iterate (@Beroal.Init.id _) x) (cycle x nil).
Proof.
refine (fun x => _).
refine (ntheq_eqst _ _ _).
refine (fun n => _).
unfold Str_nth.
refine (trans_eq (sym_eq (iterate_id_nth _ _)) _).
refine (trans_eq _ (cycle_single_nth _ _)).
simpl.
refine (refl_equal _).
Qed.
Definition unfold_cycle : forall x xs,
EqSt ((app (x :: xs) (cycle x xs))) (cycle x xs).
Proof.
refine (fun x xs => _).
refine (eqst _ _ _ _).
simpl.
refine (refl_equal _).
simpl.
refine (EqSt_reflex _).
Qed.
Definition take_cycle_id : forall x xs,
x :: xs = take (S (length xs)) (cycle x xs).
Proof.
refine (fun x xs => take_app_exact _ _).
Qed.
Definition cycle_cyclic : forall x xs, cyclic (S (length xs)) (cycle x xs).
Proof.
refine (fun x xs => _).
unfold cyclic.
refine (match @drop_app_exact xs (cycle x xs) with
| eqst p0 p1 => _ end).
refine (eqst _ _ p0 p1).
Qed.
Definition cyclic_tl : forall period xs,
cyclic period xs -> cyclic period (tl xs).
Proof.
unfold cyclic.
refine (fun period xs eq0 => _).
destruct eq0 as [p0 p1].
refine (eq_ind _ (fun dep => EqSt _ dep) p1 _ (tl_nth_tl _ _)).
Qed.
Definition cyclic_drop : forall period xs,
cyclic period xs -> forall n, cyclic period (Str_nth_tl n xs).
Proof.
refine (fun period xs eq0 => fix rec (n : nat) := _).
destruct n as [|pn].
refine (eq0).
simpl.
refine (eq_ind _ (cyclic period) (cyclic_tl (rec _)) _ (tl_nth_tl _ _)).
Qed.
Definition cyclic_hd_eq : forall xs ys,
cyclic 1 xs -> cyclic 1 ys -> hd xs = hd ys -> EqSt xs ys.
Proof.
unfold cyclic.
simpl.
refine (cofix rec xs ys cx cy eq0 : EqSt _ _ := _).
refine (eqst _ _ _ _).
refine (eq0).
destruct cx as [cx0 cx1].
destruct cy as [cy0 cy1].
refine (rec _ _ cx1 cy1 (trans_eq (sym_eq cx0) (trans_eq eq0 cy0))).
Qed.
Definition eqst_many : forall n xs ys, take n xs = take n ys
-> EqSt (Str_nth_tl n xs) (Str_nth_tl n ys) -> EqSt xs ys.
Proof.
refine (cofix rec (n : nat) (xs ys : Stream e) : _ -> _ -> EqSt _ _ := _).
destruct n as [|pn].
refine (fun _ p => p).
simpl.
refine (fun eq0 eq1 => _).
refine (eqst _ _
(f_equal (@List.hd _ (hd xs)) eq0)
(rec _ _ _ (f_equal (@List.tail _) eq0) eq1)).
Qed.
(* cycle_uncurry roth_ex cycle_rotate_tl cycle_rotate_drop; rep (length xs) roth = id *)
Definition cycle_rotate_tl_app_nil : forall x0 x1 xs,
EqSt (tl (cycle x0 (x1 :: xs)))
(app nil (cycle x1 (xs ++ (x0 :: nil)))).
Proof.
refine (fun x0 x1 xs => _).
refine (cofix recx : EqSt _ _ := _).
refine (eqst _ _ _ _).
simpl.
refine (refl_equal _).
refine ((_ : forall ys, EqSt (app ys (cycle x0 (x1 :: xs)))
((app (ys ++ x0 :: nil) (cycle x1 (xs ++ x0 :: nil))))
) xs).
refine (cofix recy (ys : list e)
: EqSt (app ys (cycle x0 (x1 :: xs)))
((app (ys ++ x0 :: nil) (cycle x1 (xs ++ x0 :: nil))))
:= _).
destruct ys as [| y0 yss].
refine (eqst _ _ _ _).
simpl.
refine (refl_equal _).
refine (recx).
refine (eqst _ _ _ _).
simpl.
refine (refl_equal _).
refine (recy yss).
Qed.
End element.
Require Coq.Arith.Plus.
Section Stream_nat.
Definition enum := iterate S.
Definition enum_nth n s : Str_nth n (enum s) = n + s.
Proof.
refine (fix rec (n : nat) {struct n} := fun s => _).
destruct n as [|pn].
unfold Str_nth.
simpl.
refine (refl_equal _).
unfold Str_nth.
simpl.
change (Str_nth pn (enum (S s)) = S pn + s).
refine (trans_eq (rec _ _) (sym_eq (Coq.Arith.Plus.plus_Snm_nSm _ _))).
Qed.
Definition enum_step step := iterate (plus step).
Definition enum_step_nth step n start0
: Str_nth n (enum_step step start0) = n * step + start0.
Proof.
refine (fun step => fix rec (n : nat) {struct n} := fun start0 => _).
destruct n as [|pn].
unfold Str_nth.
simpl.
refine (refl_equal _).
change (Str_nth pn (enum_step step (step + start0))
= step + pn * step + start0).
refine (trans_eq (rec _ _)
(trans_eq (Coq.Arith.Plus.plus_permute _ _ _)
(Coq.Arith.Plus.plus_assoc _ _ _))).
Qed.
End Stream_nat.
Definition zip_with (e0 e1 e2 : Type) (f : e0 -> e1 -> e2)
:= fix rec (xs : list e0) (ys : Stream e1) := match xs with
| nil => nil
| List.cons x xs => match ys with
| Streams.Cons y ys => List.cons (f x y) (rec xs ys) end
end.
Definition zip (e0 e1 : Type) := @zip_with e0 e1 _
(fun x0 x1 => (x0, x1)).