MathClasses.theory.streams

Require Export Streams.
Require Import peano_naturals abstract_algebra.

Section streams.
Context `{Setoid A}.

CoInductive Stream_eq_coind (s1 s2: A) : Prop :=
  stream_eq_coind : hd s1 = hd s2 Stream_eq_coind (tl s1) (tl s2) Stream_eq_coind s1 s2.

Global Instance stream_eq: Equiv (A) := Stream_eq_coind.

Global Instance: Setoid (A).
Proof.
  split.
    cofix FIX.
    now constructor.
   cofix FIX. intros ? ? E.
   constructor.
    symmetry. now destruct E.
   apply FIX. now destruct E.
  cofix FIX. intros ? ? ? E1 E2.
  constructor.
   transitivity (hd y). now destruct E1. now destruct E2.
  apply FIX with (tl y). now destruct E1. now destruct E2.
Qed.

Global Instance: Proper ((=) ==> (=)) (@Cons A).
Proof.
  intros ? ? E.
  constructor.
   simpl. now rewrite E.
  easy.
Qed.

Global Instance: Proper ((=) ==> (=)) (@hd A).
Proof. now intros ? ? []. Qed.

Global Instance: Proper ((=) ==> (=)) (@tl A).
Proof. now intros ? ? []. Qed.

Lemma Str_nth_tl_S (s : A) n : Str_nth_tl (S n) s tl (Str_nth_tl n s).
Proof. now rewrite tl_nth_tl. Qed.

Global Instance: Proper ((=) ==> (=) ==> (=)) (@Str_nth_tl A).
Proof.
  intros n m E1 ? ? E2.
  unfold equiv, peano_naturals.nat_equiv in E1.
  rewrite E1. clear E1 n.
  induction m.
   easy.
  simpl. rewrite <-2!tl_nth_tl.
  now rewrite IHm.
Qed.

Global Instance: Proper ((=) ==> (=) ==> (=)) (@Str_nth A).
Proof.
  intros ? ? E1 ? ? E2.
  unfold Str_nth.
  now rewrite E1, E2.
Qed.

Lemma stream_eq_Str_nth s1 s2 : s1 = s2 n, Str_nth n s1 = Str_nth n s2.
Proof.
  split.
   intros E ?. now rewrite E.
  revert s1 s2.
  cofix FIX.
  intros s1 s2 E.
  constructor.
   now apply (E O).
  apply FIX.
  intros. now apply (E (S n)).
Qed.

Global Instance ForAll_proper `{!Proper ((=) ==> iff) (P : A Prop)} :
  Proper ((=) ==> iff) (ForAll P).
Proof.
  assert ( x y, x = y ForAll P x ForAll P y).
   cofix FIX.
   intros ? ? E1 E2.
   constructor.
    rewrite <-E1. now destruct E2.
   apply FIX with (tl x).
    now rewrite E1.
   now destruct E2.
  intros ? ? E1. firstorder.
Qed.

Lemma ForAll_tl (P : A Prop) s : ForAll P s ForAll P (tl s).
Proof. apply (ForAll_Str_nth_tl 1). Qed.

Lemma ForAll_True (s : A) : ForAll (λ _, True) s.
Proof. revert s. cofix. intros. constructor; trivial. Qed.

Definition EventuallyForAll (P : A Prop) := ForAll (λ s, P s P (tl s)).

Lemma EventuallyForAll_tl P s : EventuallyForAll P s EventuallyForAll P (tl s).
Proof. repeat intro. now apply ForAll_tl. Qed.

Lemma EventuallyForAll_Str_nth_tl P n s :
  EventuallyForAll P s EventuallyForAll P (Str_nth_tl n s).
Proof.
  revert s.
  induction n.
   easy.
  intros. now apply IHn, EventuallyForAll_tl.
Qed.

Global Instance EventuallyForAll_proper `{!Proper ((=) ==> iff) (P : A Prop)} :
  Proper ((=) ==> iff) (EventuallyForAll P).
Proof.
  assert (Proper ((=) ==> iff) (λ s, P s P (tl s))).
   intros ? ? E.
   now rewrite E.
  intros ? ? E.
  now rewrite E.
Qed.

CoFixpoint iterate (f:A A) (x:A) : A := x ::: iterate f (f x).
CoFixpoint repeat (x:A) : A := x ::: repeat x.

End streams.

Section more.
Context `{Setoid A} `{Setoid B}.

CoInductive ForAllIf (PA : A Prop) (PB : B Prop) : A B Prop :=
  ext_if : s1 s2, (PA s1 PB s2) ForAllIf PA PB (tl s1) (tl s2) ForAllIf PA PB s1 s2.

Global Instance ForAllIf_proper `{!Proper ((=) ==> iff) (PA : A Prop)} `{!Proper ((=) ==> iff) (PB : B Prop)} :
  Proper ((=) ==> (=) ==> iff) (ForAllIf PA PB).
Proof.
  assert ( x1 y1 x2 y2, x1 = y1 x2 = y2 ForAllIf PA PB x1 x2 ForAllIf PA PB y1 y2) as P.
   cofix FIX.
   intros ? ? ? ? E1 E2 E3.
   constructor.
    rewrite <-E1, <-E2. now destruct E3.
   apply FIX with (tl x1) (tl x2).
     now rewrite E1.
    now rewrite E2.
   now destruct E3.
  repeat intro. now split; apply P.
Qed.

Global Instance map_proper `{!Proper ((=) ==> (=)) (f : A B)} :
  Proper ((=) ==> (=)) (map f).
Proof.
  cofix FIX.
  intros ? ? E.
  constructor.
   simpl. destruct E as [E]. now rewrite E.
  simpl. apply FIX. now apply E.
Qed.

Context `{Setoid C}.
Global Instance zipWith_proper `{!Proper ((=) ==> (=) ==> (=)) (f : A B C)} :
  Proper ((=) ==> (=) ==> (=)) (zipWith f).
Proof.
  cofix FIX.
  intros ? ? E1 ? ? E2.
  constructor.
   simpl. destruct E1 as [E1], E2 as [E2]. now rewrite E1, E2.
  simpl. apply FIX. now apply E1. now apply E2.
Qed.
End more.