Definition: iterate_functor
iterate_functor(I;x,y.R[x; y];T.F[T];a)==r F[⋂b:{x:I| R[a; x]} iterate_functor(I;x,y.R[x; y];T.F[T];b)]

Lemma: iterate_functor_wf
[I:Type]. ∀[R:I ⟶ I ⟶ ℙ].
  ∀[F:Type ⟶ Type]. ∀[i:I].  (iterate_functor(I;x,y.R[x;y];T.F[T];i) ∈ Type) supposing tcWO(I;x,y.R[x;y])

Definition: general_corec
general_corec(I;x,y.R[x; y];T.F[T]) ==  ⋂a:I. iterate_functor(I;x,y.R[x; y];T.F[T];a)

Lemma: general_corec_wf
[I:Type]. ∀[R:I ⟶ I ⟶ ℙ].
  ∀[F:Type ⟶ Type]. (general_corec(I;x,y.R[x;y];T.F[T]) ∈ Type) supposing tcWO(I;x,y.R[x;y])

Definition: corec
For any function F: Type -> Type, the iterates  F^n(Top), n ∈ ℕ form family
of types and ⋂n:ℕF^n(Top) is type. 
If is monotone and continuous (preserves omega limits) then the intersection
is the greatest fixpoint for F  (see corec-ext)⋅

corec(T.F[T]) ==  ⋂n:ℕprimrec(n;Top;λ,T. F[T])

Lemma: corec_wf
[F:Type ⟶ Type]. (corec(T.F[T]) ∈ Type)

Lemma: corec-valueall-type
[F:Type ⟶ Type]
  (valueall-type(corec(T.F[T]))) supposing ((∃n:ℕvalueall-type(F^n Top)) and (∀A,B:Type.  (A ≡  F[A] ≡ F[B])))

Lemma: corec-value-type
[F:Type ⟶ Type]
  (value-type(corec(T.F[T]))) supposing ((∃n:ℕvalue-type(F^n Top)) and (∀A,B:Type.  (A ≡  F[A] ≡ F[B])))

Lemma: corec-ext1
[F:Type ⟶ Type]. corec(T.F[T]) ≡ F[corec(T.F[T])] supposing Continuous+(T.F[T])

Lemma: corec-ext
[F:Type ⟶ Type]. corec(T.F[T]) ≡ F[corec(T.F[T])] supposing ContinuousMonotone(T.F[T])

Lemma: corec-greatest
[F:Type ⟶ Type]. ∀[X:Type]. X ⊆corec(T.F[T]) supposing X ≡ F[X] supposing Monotone(T.F[T])

Definition: isect-family
a:A. F[a] ==  λp.⋂a:A. (F[a] p)

Lemma: isect-family_wf
[P,A:Type]. ∀[F:A ⟶ P ⟶ Type].  (⋂a:A. F[a] ∈ P ⟶ Type)

Lemma: isect-family-wf2
[P:𝕌{j}]. ∀[A:Type]. ∀[F:A ⟶ P ⟶ Type].  (⋂a:A. F[a] ∈ P ⟶ Type)

Definition: sub-family
F ⊆ ==  ∀p:P. ((F p) ⊆(G p))

Lemma: sub-family_wf
[P:Type]. ∀[F,G:P ⟶ Type].  (F ⊆ G ∈ ℙ)

Lemma: sub-family_transitivity
[P:Type]. ∀[F,G,H:P ⟶ Type].  (F ⊆ H) supposing (F ⊆ and G ⊆ H)

Lemma: sub-isect-family
[P:Type]. ∀[G:P ⟶ Type]. ∀[A:Type]. ∀[F:A ⟶ P ⟶ Type].  G ⊆ ⋂a:A. F[a] supposing ∀a:A. G ⊆ F[a]

Definition: ext-family
F ≡ ==  ∀p:P. p ≡ p

Lemma: ext-family_wf
[P:Type]. ∀[F,G:P ⟶ Type].  (F ≡ G ∈ ℙ)

Lemma: ext-family-iff
[P:Type]. ∀[F,G:P ⟶ Type].  uiff(F ≡ G;F ⊆ G ∧ G ⊆ F)

Definition: family-monotone
family-monotone{i:l}(P;H) ==  ∀F,G:P ⟶ Type.  (F ⊆  F ⊆ G)

Lemma: family-monotone_wf
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].  (family-monotone{i:l}(P;H) ∈ ℙ')

Definition: type-family-continuous
type-family-continuous{i:l}(P;H) ==  ∀[X:ℕ ⟶ P ⟶ Type]. ⋂n:ℕ(X n) ⊆ H ⋂n:ℕn

Lemma: type-family-continuous_wf
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].  (type-family-continuous{i:l}(P;H) ∈ ℙ')

Definition: corec-family
family of type parameterized by is member of
the type ⌜P ⟶ Type⌝.
The family of types ⌜λp.Top⌝ is the greatest such family
(under the pointwise subtype ordering).
If maps ⌜P ⟶ Type⌝ to ⌜P ⟶ Type⌝then the intersection (as family)
of the iterates of is the corecursive family defined by H.

If satisfies the properties ⌜type-family-continuous{i:l}(P;H)⌝
and ⌜family-monotone{i:l}(P;H)⌝then the ⌜corec-family(H)⌝ is an
extensional fixed point of H.
(See lemma corec-family-ext)⋅

corec-family(H) ==  ⋂n:ℕH^n p.Top)

Lemma: corec-family_wf
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].  (corec-family(H) ∈ P ⟶ Type)

Lemma: corec-family-wf2
[P:𝕌{j}]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].  (corec-family(H) ∈ P ⟶ Type)

Lemma: corec-sub-family
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].  corec-family(H) ⊆ corec-family(H) supposing family-monotone{i:l}(P;H)

Lemma: sub-corec-family
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].
  corec-family(H) ⊆ corec-family(H) supposing type-family-continuous{i:l}(P;H)

Lemma: corec-family-ext
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].
  corec-family(H) ≡ corec-family(H) supposing type-family-continuous{i:l}(P;H) ∧ family-monotone{i:l}(P;H)

Lemma: fix-corec-family-partial1
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type]. ∀[A:Type].
  (∀[F:(P ⟶ Type) ⟶ P ⟶ Type]. ∀[f:(i:P ⟶ (corec-family(H) i) ⟶ partial(A))
                                      ⟶ i:P
                                      ⟶ (corec-family(H) i)
                                      ⟶ partial(A)].
     (fix(f) ∈ i:P ⟶ (corec-family(H) i) ⟶ partial(A))) supposing 
     (mono(A) and 
     value-type(A))

Lemma: fix_wf_corec-family-partial1
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type]. ∀[A:Type].
  (∀[f:⋂T:P ⟶ Type. ((i:P ⟶ (T i) ⟶ partial(A)) ⟶ i:P ⟶ (H[T] i) ⟶ partial(A))]
     (fix(f) ∈ i:P ⟶ (corec-family(H) i) ⟶ partial(A))) supposing 
     ((family-monotone{i:l}(P;H) ∧ type-family-continuous{i:l}(P;H)) and 
     mono(A) and 
     value-type(A))

Lemma: fix_wf_corec-family-partial-nat
[P:Type]. ∀[H:(P ⟶ Type) ⟶ P ⟶ Type].
  ∀[f:⋂T:P ⟶ Type. ((i:P ⟶ (T i) ⟶ partial(ℕ)) ⟶ i:P ⟶ (H[T] i) ⟶ partial(ℕ))]
    (fix(f) ∈ i:P ⟶ (corec-family(H) i) ⟶ partial(ℕ)) 
  supposing family-monotone{i:l}(P;H) ∧ type-family-continuous{i:l}(P;H)

Definition: param-co-W
The co-recursive family of parameterized co-W types.
For given parameter p, member of ⌜pco-W p⌝ will be
pair ⌜<a, f>⌝ where ⌜a ∈ A[p]⌝ and is function with
domain ⌜B[p; a]⌝For in the domain of f, ⌜b⌝ is member
of the co-W type in family that has parameter ⌜C[p;
                                                 a;
                                                 b]⌝.⋅

pco-W ==
  corec-family(λW,p. (a:A[p] × (b:B[p; a] ⟶ (W 
                                              C[p;
                                                a;
                                                b]))))

Lemma: param-co-W_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].  (pco-W ∈ P ⟶ Type)

Lemma: param-co-W-ext
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
  pco-W ≡ λp.(a:A[p] × (b:B[p;a] ⟶ (pco-W C[p;a;b])))

Definition: pcw-step
step in path through parameterized-co-W type
is triple ⌜<p, w, d>⌝ where ⌜p ∈ P⌝ is the current parameter,
w ∈ pco-W p⌝ is the current "co-tree" (i.e. non-well-founded tree)
and is "decision",
When is ⌜inl b⌝ where is member of the domain
of ⌜snd(w)⌝ (i.e. member of ⌜B[p; fst(w)]⌝)
then the path will continue with next step.
When is ⌜inr ⋅ ⌝ then the path ends at this step.⋅

pcw-step(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                      a;
                                      b]) ==
  p:P × w:pco-W p × (B[p; fst(w)]?)

Lemma: pcw-step_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
  (pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b]) ∈ Type)

Definition: pcw-final-step
pcw-final-step(s) ==  let p,w,d in ↑isr(d)

Lemma: pcw-final-step_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
[s:pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])].
  (pcw-final-step(s) ∈ ℙ)

Definition: pcw-step-agree
The first and second parts of the triple (the parameter and tree w') 
agree with the given parameter p1 and tree w.⋅

StepAgree(s;p1;w) ==  let p,w',b in (p p1 ∈ P) ∧ (w' w ∈ (pco-W p1))

Lemma: pcw-step-agree_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
[s:pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])]. ∀[p1:P]. ∀[w:pco-W p1].
  (StepAgree(s;p1;w) ∈ ℙ)

Definition: pcw-steprel
If the "decision" in step s1 = ⌜<p, w, d>⌝ is ⌜inl b⌝
then the next step s2 = ⌜<p', w', d'>⌝ must
have p' = ⌜C[p;
             a;
             b]⌝ and w' = ⌜b⌝ (where = ⌜<a, f>⌝).
If the path "ended" at step s1, then later steps are irrelevant
so there is no restriction.⋅

StepRel(s1;s2) ==
  let p,w,d s1 in 
  let a,f 
  in case d
      of inl(b) =>
      StepAgree(s2;C[p;
                     a;
                     b];f b)
      inr(x) =>
      True

Lemma: pcw-steprel_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
[s1,s2:pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])].
  (StepRel(s1;s2) ∈ ℙ)

Definition: pcw-consistent-steps
pcw-consistent-steps(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                                  a;
                                                  b];s1;s2) ==
  let p,w,d s1 in 
  let p',w',d' s2 in 
  (p p' ∈ P) ∧ (w w' ∈ (pco-W p)) ∧ ((↑isl(d))  (d d' ∈ (B[p; fst(w)]?)))

Lemma: pcw-consistent-steps_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
[s1,s2:pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])].
  (pcw-consistent-steps(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b];s1;s2) ∈ ℙ)

Definition: pcw-path
full path through co-W type is an infinite sequence of steps
such that each successive step agrees with the previous step.⋅

Path ==
  {path:ℕ ⟶ pcw-step(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                                   a;
                                                   b])| 
   ∀i:ℕStepRel(path i;path (i 1))} 

Lemma: pcw-path_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].  (Path ∈ Type)

Definition: pcw-consistent-paths
pcw-consistent-paths(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                                  a;
                                                  b];f;g) ==
  ∀n:ℕ
    ((¬pcw-final-step(f n))
     ((f n)
       (g n)
       ∈ pcw-step(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                               a;
                                               b])))

Lemma: pcw-consistent-paths_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[f,g:Path].
  (pcw-consistent-paths(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b];f;g) ∈ ℙ)

Definition: pcw-path-rel
pcw-path-rel(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                          a;
                                          b];f;g) ==
  pcw-consistent-paths(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                                    a;
                                                    b];f;g)
  ∧ (∃n:ℕ((∀i:ℕn. pcw-final-step(f i))) ∧ pcw-final-step(f n) ∧ pcw-final-step(g n))))

Lemma: pcw-path-rel_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[f,g:Path].
  (pcw-path-rel(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b];f;g) ∈ ℙ)

Lemma: pcw-path-shift
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
  ∀path:Path. x.(path (x 1)) ∈ Path)

Definition: pcw-pp
PartialPath ==
  {nss:n:ℕ × (ℕn ⟶ pcw-step(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                                          a;
                                                          b]))| 
   let n,ss nss 
   in ∀i:ℕ1. StepRel(ss i;ss (i 1))} 

Lemma: pcw-pp_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].  (PartialPath ∈ Type)

Definition: pcw-partial
pcw-partial(path;n) ==  <n, path>

Lemma: pcw-partial_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[path:Path]. ∀[n:ℕ].
  (pcw-partial(path;n) ∈ PartialPath)

Definition: pcw-pp-null
pcw-pp-null(pp) ==  let n,ss pp in n ≤0

Lemma: pcw-pp-null_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[pp:PartialPath].
  (pcw-pp-null(pp) ∈ 𝔹)

Definition: pcw-pp-head
pcw-pp-head(pp) ==  let n,ss pp in ss 0

Lemma: pcw-pp-head_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[pp:PartialPath].
  pcw-pp-head(pp) ∈ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b]) supposing ¬↑pcw-pp-null(pp)

Definition: pcw-pp-tail
pcw-pp-tail(pp) ==  let n,ss pp in <1, λx.(ss (x 1))>

Lemma: pcw-pp-tail_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[pp:PartialPath].
  pcw-pp-tail(pp) ∈ PartialPath supposing ¬↑pcw-pp-null(pp)

Definition: pcw-pp-barred
partial path ⌜<n, ss>⌝ is barred if it is non-empty and the last step
has "decision" inr ⋅ .
This means that the path does not continue with decision inl b
that picks member of the domain of ⌜snd(w)⌝.⋅

Barred(pp) ==  let n,ss pp in 0 < n ∧ let p,w,d ss (n 1) in ↑isr(d)

Lemma: pcw-pp-barred_wf0
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
[pp:n:ℕ × (ℕn ⟶ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b]))].
  (Barred(pp) ∈ ℙ)

Lemma: pcw-pp-barred_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[pp:PartialPath].
  (Barred(pp) ∈ ℙ)

Lemma: decidable__pcw-pp-barred
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
  ∀pp:n:ℕ × (ℕn ⟶ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])). Dec(Barred(pp))

Definition: param-W
For each parameter ⌜par ∈ P⌝the corresponding type
in the parameterized family of W-types is the subtype of the
corresponding parameterized co-inductive family of co-W types
containing those trees, w, such that every path starting at w
is barred.  ⋅

pW ==  λpar.{w:pco-W par| ∀path:Path. (StepAgree(path 0;par;w)  (↓∃n:ℕBarred(pcw-partial(path;n))))} 

Lemma: param-W_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].  (pW ∈ P ⟶ Type)

Definition: pW-sup
pW-sup(a;f) ==  <a, f>

Lemma: pW-sup_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[par:P]. ∀[a:A[par]].
[f:b:B[par;a] ⟶ (pW C[par;a;b])].
  (pW-sup(a;f) ∈ pW par)

Lemma: param-W-ext
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P].
  pW ≡ λp.(a:A[p] × (b:B[p;a] ⟶ (pW C[p;a;b])))

Lemma: equal-implies-member-param-W
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[p:P]. ∀[w:pW p].
[w':pco-W p].
  w' ∈ pW supposing w' ∈ (pco-W p)

Definition: param-W-rel
param-W-rel(P;p.A[p];p,a.B[p; a];p,a,b.C[p;
                                         a;
                                         b];par;w) ==
  λn,ss,s. if (0) < (n)  then (↑isl(snd(snd((ss (n 1)))))) ∧ StepRel(ss (n 1);s)  else StepAgree(s;par;w)

Lemma: param-W-rel_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[par:P]. ∀[w:pW par].
  (param-W-rel(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b];par;w) ∈ n:ℕ
   ⟶ (ℕn ⟶ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b]))
   ⟶ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b])
   ⟶ ℙ)

Lemma: pcw-pp-lemma
P:Type. ∀A:P ⟶ Type. ∀B:p:P ⟶ A[p] ⟶ Type. ∀C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P. ∀par:P. ∀w:pW par. ∀n:ℕ. ∀m:ℕn.
ss:ℕn ⟶ pcw-step(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b]).
  ((∀x:ℕn. (param-W-rel(P;p.A[p];p,a.B[p;a];p,a,b.C[p;a;b];par;w) ss (ss x)))
   (fst(snd((ss m))) ∈ pW (fst((ss m)))))

Definition: pW-rec
let ind(p,a,f,G) ind[p;
                       a;
                       f;
                       G] in 
letrec F(p,w) let a,f=w in 
                ind(p,a,f,λb.F(C[p;
                                 a;
                                 b],f(b)) in 
F(par;w)
==r let a,f 
    in ind[par;
           a;
           f;
           λb.let ind(p,a,f,G) ind[p;
                                     a;
                                     f;
                                     G] in 
              letrec F(p,w) let a,f=w in 
                              ind(p,a,f,λb.F(C[p;
                                               a;
                                               b],f(b)) in 
              F(C[par;
                  a;
                  b];f b)]

Lemma: pW-rec_wf
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type]. ∀[C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P]. ∀[Q:par:P ⟶ (pW par) ⟶ ℙ].
[ind:par:P
      ⟶ a:A[par]
      ⟶ f:(b:B[par;a] ⟶ (pW C[par;a;b]))
      ⟶ (b:B[par;a] ⟶ Q[C[par;a;b];f b])
      ⟶ Q[par;pW-sup(a;f)]]. ∀[par:P]. ∀[w:pW par].
  (let ind(p,a,f,G) ind[p;a;f;G] in 
   letrec F(p,w) let a,f=w in 
                   ind(p,a,f,λb.F(C[p;a;b],f(b)) in 
   F(par;w) ∈ Q[par;w])

Lemma: param-W-induction
[P:Type]. ∀[A:P ⟶ Type]. ∀[B:p:P ⟶ A[p] ⟶ Type].
  ∀C:p:P ⟶ a:A[p] ⟶ B[p;a] ⟶ P
    ∀[Q:par:P ⟶ (pW par) ⟶ ℙ]
      ((∀par:P. ∀a:A[par]. ∀f:b:B[par;a] ⟶ (pW C[par;a;b]).  ((∀b:B[par;a]. Q[C[par;a;b];f b])  Q[par;pW-sup(a;f)]))
       (∀par:P. ∀w:pW par.  Q[par;w]))

Definition: pw-evenodd
pw-evenodd() ==  pW

Lemma: pw-evenodd_wf
pw-evenodd() ∈ 𝔹 ⟶ Type

Lemma: evodd-induction
[Q:b:𝔹 ⟶ (pw-evenodd() b) ⟶ ℙ]
  ((∀b:𝔹. ∀a:b tt?. ∀f:case of inl(x) => Void inr(x) => Unit ⟶ (pw-evenodd() bb)).
      ((∀x:case of inl(x) => Void inr(x) => Unit. Q[¬bb;f x])  Q[b;pW-sup(a;f)]))
   (∀b:𝔹. ∀n:pw-evenodd() b.  Q[b;n]))

Definition: evodd-zero
evodd-zero() ==  pW-sup(inl Ax;λx.x)

Lemma: evodd-zero_wf
evodd-zero() ∈ pw-evenodd() tt

Definition: evodd-succ
evodd-succ(n) ==  pW-sup(inr Ax x.n)

Lemma: evodd-succ_wf
[b:𝔹]. ∀[n:pw-evenodd() bb)].  (evodd-succ(n) ∈ pw-evenodd() b)

Lemma: evodd-induction2
[Q:b:𝔹 ⟶ (pw-evenodd() b) ⟶ ℙ]
  (Q[tt;evodd-zero()]
   (∀b:𝔹. ∀x:pw-evenodd() b.  (Q[b;x]  Q[¬bb;evodd-succ(x)]))
   (∀b:𝔹. ∀n:pw-evenodd() b.  Q[b;n]))

Lemma: evodd-induction2-ext
[Q:b:𝔹 ⟶ (pw-evenodd() b) ⟶ ℙ]
  (Q[tt;evodd-zero()]
   (∀b:𝔹. ∀x:pw-evenodd() b.  (Q[b;x]  Q[¬bb;evodd-succ(x)]))
   (∀b:𝔹. ∀n:pw-evenodd() b.  Q[b;n]))

Definition: evodd-enum
evodd-enum(n) ==  primrec(n;<tt, evodd-zero()>i,x. let b,z in <¬bb, evodd-succ(z)>)

Lemma: evodd-enum_wf
[n:ℕ]. (evodd-enum(n) ∈ b:𝔹 × (pw-evenodd() b))

Lemma: evodd-enum-surjection
Surj(ℕ;b:𝔹 × (pw-evenodd() b);λn.evodd-enum(n))

Definition: cw-step
cw-step(A;a.B[a]) ==  pcw-step(Unit;p.A;p,a.B[a];p,a,b.⋅)

Lemma: cw-step_wf
[A:Type]. ∀[B:A ⟶ Type].  (cw-step(A;a.B[a]) ∈ Type)

Definition: W
parameterized family of types with the parameter type Unit 
must have the "C" function ⌜λp,a,b. ⋅⌝.
Then applying this family to the paramter ⌜⋅⌝we get the W-type
as an instance of the more general parameterized family of types.⋅

W(A;a.B[a]) ==  pW ⋅

Lemma: W_wf
[A:Type]. ∀[B:A ⟶ Type].  (W(A;a.B[a]) ∈ Type)

Definition: W-rel
W-rel(A;a.B[a];w) ==  param-W-rel(Unit;p.A;p,a.B[a];p,a,b.⋅;⋅;w)

Lemma: W-rel_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[w:W(A;a.B[a])].
  (W-rel(A;a.B[a];w) ∈ n:ℕ ⟶ (ℕn ⟶ cw-step(A;a.B[a])) ⟶ cw-step(A;a.B[a]) ⟶ ℙ)

Lemma: cw-pp-lemma
A:Type. ∀B:A ⟶ Type. ∀w:W(A;a.B[a]). ∀n:ℕ. ∀m:ℕn. ∀ss:ℕn ⟶ cw-step(A;a.B[a]).
  ((∀x:ℕn. (W-rel(A;a.B[a];w) ss (ss x)))  (fst(snd((ss m))) ∈ W(A;a.B[a])))

Lemma: pcw-pp-barred-W
[A:Type]. ∀[B:A ⟶ Type]. ∀[pp:n:ℕ × (ℕn ⟶ cw-step(A;a.B[a]))].  (Barred(pp) ∈ ℙ)

Lemma: pcw-pp-barred-W-decidable
[A:Type]. ∀[B:A ⟶ Type].  ∀n:ℕ. ∀s:ℕn ⟶ cw-step(A;a.B[a]).  (Barred(<n, s>) ∨ Barred(<n, s>)))

Lemma: W-path-lemma
A:Type. ∀B:A ⟶ Type. ∀x:W(A;a.B[a]). ∀alpha:ℕ ⟶ cw-step(A;a.B[a]).
  ((∀n:ℕ(W-rel(A;a.B[a];x) alpha (alpha n)))  (alpha ∈ Path))

Lemma: W-ext
[A:Type]. ∀[B:A ⟶ Type].  W(A;a.B[a]) ≡ a:A × (B[a] ⟶ W(A;a.B[a]))

Lemma: W-path-lemma2
A1:Type. ∀B1:A1 ⟶ Type. ∀a:A1. ∀x1:B1[a] ⟶ W(A1;a.B1[a]). ∀n:ℕ+. ∀s:ℕn ⟶ cw-step(A1;a.B1[a]). ∀a1:A1.
w1:b:B1[a1] ⟶ (pco-W ⋅). ∀x:B1[a1]. ∀a2:A1. ∀z1:b:B1[a2] ⟶ (pco-W ⋅).
  ((∀k:ℕn. (W-rel(A1;a.B1[a];<a, x1>(s k)))
   ((s (n 1)) = <⋅, <a1, w1>inl x> ∈ cw-step(A1;a.B1[a]))
   ((w1 x) = <a2, z1> ∈ (pco-W ⋅))
   (z1 ∈ b:B1[a2] ⟶ W(A1;a.B1[a])))

Lemma: W-elimination-facts
A:Type. ∀B:A ⟶ Type. ∀w:W(A;a.B[a]).
  ((cw-step(A;a.B[a]) ∈ Type)
  ∧ (W-rel(A;a.B[a];w) ∈ n:ℕ ⟶ (ℕn ⟶ cw-step(A;a.B[a])) ⟶ cw-step(A;a.B[a]) ⟶ ℙ)
  ∧ (W(A;a.B[a]) ∈ Type)
  ∧ (W(A;a.B[a]) ⊆(pco-W ⋅))
  ∧ (∀n:ℕ. ∀s:ℕn ⟶ cw-step(A;a.B[a]).  (Barred(<n, s>) ∨ Barred(<n, s>))))
  ∧ (∀alpha:ℕ ⟶ cw-step(A;a.B[a]). ((∀n:ℕ(W-rel(A;a.B[a];w) alpha (alpha n)))  (alpha ∈ Path)))
  ∧ (∀[pp:n:ℕ × (ℕn ⟶ cw-step(A;a.B[a]))]. (Barred(pp) ∈ ℙ))
  ∧ (∀alpha:ℕ ⟶ cw-step(A;a.B[a]). ((∀n:ℕ(W-rel(A;a.B[a];w) alpha (alpha n)))  (↓∃n:ℕBarred(<n, alpha>))))
  ∧ (∀a:A. ∀x1:B[a] ⟶ W(A;a.B[a]). ∀n:ℕ+. ∀s:ℕn ⟶ cw-step(A;a.B[a]). ∀a1:A. ∀w1:b:B[a1] ⟶ (pco-W ⋅). ∀x:B[a1]. ∀a2:A.
     ∀z1:b:B[a2] ⟶ (pco-W ⋅).
       ((∀k:ℕn. (W-rel(A;a.B[a];<a, x1>(s k)))
        ((s (n 1)) = <⋅, <a1, w1>inl x> ∈ cw-step(A;a.B[a]))
        ((w1 x) = <a2, z1> ∈ (pco-W ⋅))
        (z1 ∈ B[a2] ⟶ W(A;a.B[a])))))

Definition: Wsup
Wsup(a;b) ==  <a, b>

Lemma: Wsup_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[a:A]. ∀[b:B[a] ⟶ W(A;a.B[a])].  (Wsup(a;b) ∈ W(A;a.B[a]))

Lemma: W-induction1
[A:Type]. ∀[B:A ⟶ Type]. ∀[Q:W(A;a.B[a]) ⟶ ℙ].
  ((∀a:A. ∀f:B[a] ⟶ W(A;a.B[a]).  ((∀b:B[a]. Q[f b])  Q[Wsup(a;f)]))  (∀w:W(A;a.B[a]). Q[w]))

Lemma: W-induction1-extract
[A:Type]. ∀[B:A ⟶ Type]. ∀[Q:W(A;a.B[a]) ⟶ ℙ].
  ((∀a:A. ∀f:B[a] ⟶ W(A;a.B[a]).  ((∀b:B[a]. Q[f b])  Q[Wsup(a;f)]))  (∀w:W(A;a.B[a]). Q[w]))

Definition: W_ind
W_ind(F;w) ==  letrec H(par)=λw.let a,f in b.(H Ax (f b))) in H(Ax) w

Lemma: W_ind_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[Q:W(A;a.B[a]) ⟶ ℙ].
[F:∀a:A. ∀f:B[a] ⟶ W(A;a.B[a]).  ((∀b:B[a]. Q[f b])  Q[Wsup(a;f)])]. ∀[w:W(A;a.B[a])].
  (W_ind(F;w) ∈ Q[w])

Lemma: W-induction
[A:Type]. ∀[B:A ⟶ Type]. ∀[Q:W(A;a.B[a]) ⟶ ℙ].
  ((∀a:A. ∀f:B[a] ⟶ W(A;a.B[a]).  ((∀b:B[a]. Q[f b])  Q[Wsup(a;f)]))  (∀w:W(A;a.B[a]). Q[w]))

Definition: W-rec
W-rec(a,f,r.F[a;
              f;
              r];w)
==r let a,f 
    in F[a;
         f;
         λb.W-rec(a,f,r.F[a;
                          f;
                          r];f b)]

Lemma: W-rec_wf
[T,A:Type]. ∀[B:A ⟶ Type]. ∀[F:a:A ⟶ (B[a] ⟶ W(A;a.B[a])) ⟶ (B[a] ⟶ T) ⟶ T]. ∀[w:W(A;a.B[a])].
  (W-rec(a,f,r.F[a;f;r];w) ∈ T)

Lemma: W_subtype
[A1,A2:Type]. ∀[B1:A1 ⟶ Type]. ∀[B2:A2 ⟶ Type].
  (W(A1;a.B1[a]) ⊆W(A2;a.B2[a])) supposing ((∀a:A1. (B2[a] ⊆B1[a])) and (A1 ⊆A2))

Definition: Wcmp
Wcmp(A;a.B[a];leq) ==
  fix((λWcmp,leq,w1,w2. if leq
                       then let a,f w1 
                            in ∀x:B[a]. ((f x) (Wcmp ff) w2)
                       else let a,f w2 
                            in ∃x:B[a]. (w1 (Wcmp tt) (f x))
                       fi )) 
  leq

Lemma: Wcmp_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[leq:𝔹].  (Wcmp(A;a.B[a];leq) ∈ W(A;a.B[a]) ⟶ W(A;a.B[a]) ⟶ ℙ)

Lemma: Wleq_weakening
[A:Type]. ∀[B:A ⟶ Type].  ∀w1,w2:W(A;a.B[a]).  ((w1 <  w2)  (w1 ≤  w2))

Lemma: Wleq_weakening2
[A:Type]. ∀[B:A ⟶ Type].  ∀w1,w2:W(A;a.B[a]).  w1 ≤  w2 supposing w1 w2 ∈ W(A;a.B[a])

Lemma: Wcmp_transitivity
[A:Type]. ∀[B:A ⟶ Type].
  ∀w1,w2,w3:W(A;a.B[a]).
    ((((w1 <  w2)  (w2 ≤  w3)  (w1 <  w3)) ∧ ((w1 ≤  w2)  (w2 <  w3)  (w1 <  w3)))
    ∧ ((w1 ≤  w2)  (w2 ≤  w3)  (w1 ≤  w3)))

Lemma: Wless_antireflexive
[A:Type]. ∀[B:A ⟶ Type]. ∀[w1:W(A;a.B[a])].  (w1 <  w1))

Lemma: W-uwellfounded_witness
λF.fix(F) ∈ ∀[A:Type]. ∀[B:A ⟶ Type].  uWellFnd(W(A;a.B[a]);w1,w2.w1 <  w2)

Lemma: W-uwellfounded
[A:Type]. ∀[B:A ⟶ Type].  uWellFnd(W(A;a.B[a]);w1,w2.w1 <  w2)

Lemma: W-measure-induction
[T,A:Type]. ∀[B:A ⟶ Type]. ∀[measure:T ⟶ W(A;a.B[a])]. ∀[P:T ⟶ ℙ].
  ((∀i:T. ((∀j:{j:T| measure[j] <  measure[i]} P[j])  P[i]))  (∀i:T. P[i]))

Lemma: W-uniform-measure-induction
[T,A:Type]. ∀[B:A ⟶ Type]. ∀[measure:T ⟶ W(A;a.B[a])]. ∀[P:T ⟶ ℙ].
  ((∀[i:T]. ((∀[j:{j:T| measure[j] <  measure[i]} ]. P[j])  P[i]))  (∀[i:T]. P[i]))

Definition: W_iterate_functor
W_iterate_functor(A;a.B[a];T.F[T];w)==r F[⋂x:{b:W(A;a.B[a])| b <  w} W_iterate_functor(A;a.B[a];T.F[T];x)]

Lemma: W_iterate_functor_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[F:Type ⟶ Type]. ∀[w:W(A;a.B[a])].  (W_iterate_functor(A;a.B[a];T.F[T];w) ∈ Type)

Definition: W_corec
This is generalization of ⌜corec(T.F[T])⌝ where instead of iterating
only over the natural numbers, we iterate over all the "ordinals" in
the type ⌜W(A;a.B[a])⌝.⋅

W_corec(A;a.B[a];T.F[T]) ==  ⋂w:W(A;a.B[a]). W_iterate_functor(A;a.B[a];T.F[T];w)

Lemma: W_corec_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[F:Type ⟶ Type].  (W_corec(A;a.B[a];T.F[T]) ∈ Type)

Definition: Wzero
isZero(w) ==  ¬B[fst(w)]

Lemma: Wzero_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[w:W(A;a.B[a])].  (isZero(w) ∈ ℙ)

Lemma: Wzero-leq
[A:Type]. ∀[B:A ⟶ Type].  ∀w:W(A;a.B[a]). (isZero(w) ⇐⇒ ∀w2:W(A;a.B[a]). (w ≤  w2))

Definition: Wsucc
Wsucc(A;a.B[a];w) ==  B[fst(w)] ≡ Unit

Lemma: Wsucc_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[w:W(A;a.B[a])].  (Wsucc(A;a.B[a];w) ∈ ℙ)

Definition: Wadd
(w1 w2) ==  fix((λWadd,w2. let a,f w2 in if zero then w1 else Wsup(a;λx.(Wadd (f x))) fi )) w2

Lemma: Wadd_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero:A ⟶ 𝔹]. ∀[w2,w1:W(A;a.B[a])].  ((w1 w2) ∈ W(A;a.B[a]))

Lemma: Wadd-assoc
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero:A ⟶ 𝔹]. ∀[w3,w2,w1:W(A;a.B[a])].  ((w1 (w2 w3)) ((w1 w2) w3) ∈ W(A;a.B[a]))

Lemma: Wleq-Wadd
[A:Type]. ∀[B:A ⟶ Type].  ∀zero:A ⟶ 𝔹. ∀w3,w2,w1:W(A;a.B[a]).  ((w1 ≤  w2)  ((w1 w3) ≤  (w2 w3)))

Lemma: Wleq-Wadd3
[A:Type]. ∀[B:A ⟶ Type].  ∀zero:A ⟶ 𝔹((∀a:A. (¬↑(zero a) ⇐⇒ B[a]))  (∀w1,w2:W(A;a.B[a]).  (w1 ≤  (w1 w2))))

Lemma: Wleq-Wadd2
[A:Type]. ∀[B:A ⟶ Type].
  ∀zero:A ⟶ 𝔹((∀a:A. (¬↑(zero a) ⇐⇒ B[a]))  (∀w3,w2,w1:W(A;a.B[a]).  ((w2 ≤  w3)  ((w1 w2) ≤  (w1 w3)))))

Lemma: Wless-Wadd
[A:Type]. ∀[B:A ⟶ Type].
  ∀zero:A ⟶ 𝔹((∀a:A. (¬↑(zero a) ⇐⇒ B[a]))  (∀w3,w2,w1:W(A;a.B[a]).  ((w2 <  w3)  ((w1 w2) <  (w1 w3)))))

Lemma: Wzero-unique
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero:A ⟶ 𝔹].
  ∀[z1,z2:W(A;a.B[a])].  z1 z2 ∈ W(A;a.B[a]) supposing isZero(z1) ∧ isZero(z2) 
  supposing (∀a1,a2:A.  ((↑(zero a1))  (↑(zero a2))  (a1 a2 ∈ A))) ∧ (∀a:A. ((¬B[a])  (↑(zero a))))

Lemma: Wadd-Wzero
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero:A ⟶ 𝔹].
  ∀[z:W(A;a.B[a])]
    ∀[w1:W(A;a.B[a])]. (((w1 z) w1 ∈ W(A;a.B[a])) ∧ ((z w1) w1 ∈ W(A;a.B[a]))) supposing isZero(z) 
  supposing (∀a:A. (↑(zero a) ⇐⇒ ¬B[a])) ∧ (∀a1,a2:A.  ((↑(zero a1))  (↑(zero a2))  (a1 a2 ∈ A)))

Definition: Wmul
(w1 w2) ==  fix((λWmul,w2. let a,f w2 in if succ then (Wmul (f ⋅w1) else Wsup(a;λx.(Wmul (f x))) fi )) w2

Lemma: Wmul_wf
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero,succ:A ⟶ 𝔹]. ∀[w2,w1:W(A;a.B[a])].
  (w1 w2) ∈ W(A;a.B[a]) supposing ∀a:A. ((↑(succ a))  (Unit ⊆B[a]))

Lemma: Wmul-Wadd
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero,succ:A ⟶ 𝔹].
  ∀[w3,w2,w1:W(A;a.B[a])].  ((w1 (w2 w3)) ((w1 w2) (w1 w3)) ∈ W(A;a.B[a])) 
  supposing ∀a:A. (((↑(succ a))  (Unit ⊆B[a])) ∧ ((↑(zero a))  B[a])))

Lemma: Wmul-assoc
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero,succ:A ⟶ 𝔹]. ∀[w3,w2,w1:W(A;a.B[a])].
  (w1 (w2 w3)) ((w1 w2) w3) ∈ W(A;a.B[a]) 
  supposing ∀a:A. (((↑(succ a))  (Unit ⊆B[a])) ∧ ((↑(zero a))  B[a])))

Lemma: Wmul-Wzero
[A:Type]. ∀[B:A ⟶ Type]. ∀[zero,succ:A ⟶ 𝔹].
  ∀[z:W(A;a.B[a])]. ∀[w1:W(A;a.B[a])]. ((w1 z) z ∈ W(A;a.B[a])) supposing isZero(z) 
  supposing ∀a:A. ((↑(succ a))  (Unit ⊆B[a]))

Lemma: Wleq-Wmul
[A:Type]. ∀[B:A ⟶ Type].
  ∀zero,succ:A ⟶ 𝔹.
    ((∀a:A. ((↑(succ a))  (Unit ⊆B[a])))
     (∀a:A. (¬↑(zero a) ⇐⇒ B[a]))
     (∀w3,w2,w1:W(A;a.B[a]).  ((w1 ≤  w2)  ((w1 w3) ≤  (w2 w3)))))

Lemma: Wmul-add-properties
[A:Type]. ∀[B:A ⟶ Type].
  ∀zero,succ:A ⟶ 𝔹.
    ((∀a:A. ((↑(succ a))  B[a] ≡ Unit))
     (∀a:A. (¬↑(zero a) ⇐⇒ B[a]))
     (∀a1,a2:A.  ((↑(zero a1))  (↑(zero a2))  (a1 a2 ∈ A)))
     (∀x,y,z:W(A;a.B[a]).
          (((x (y z)) ((x y) z) ∈ W(A;a.B[a]))
          ∧ ((x (y z)) ((x y) (x z)) ∈ W(A;a.B[a]))
          ∧ ((x (y z)) ((x y) z) ∈ W(A;a.B[a]))
          ∧ (isZero(z)  isZero(y)  (z y ∈ W(A;a.B[a])))
          ∧ (isZero(z)
             ((((x z) x ∈ W(A;a.B[a])) ∧ ((z x) x ∈ W(A;a.B[a]))) ∧ ((x z) z ∈ W(A;a.B[a])) ∧ (z ≤  x)))
          ∧ ((x ≤  y)  (((x z) ≤  (y z)) ∧ ((z x) ≤  (z y))))
          ∧ ((x <  y)  ((z x) <  (z y)))
          ∧ ((x ≤  y)  ((x z) ≤  (y z))))))

Lemma: sig-to-W
[A:Type]. ∀[B:A ⟶ Type].  ((a:A × B[a]))  W(A;a.B[a]))

Lemma: W-to-not-not-sig
[A:Type]. ∀[B:A ⟶ Type].  (W(A;a.B[a])  (¬¬(a:A × B[a]))))

Lemma: W-to-not-not-sig2
A:Type. ∀B:A ⟶ Type.  (W(A;a.B[a])  (∀R:Type. (((a:A × (B[a]  R))  R)  R)))

Lemma: not-not-sig-to-W
A:Type. ∀B:A ⟶ Type.  ((∀R:Type. (((a:A × (B[a]  R))  R)  R))  W(A;a.B[a]))

Lemma: not-not-sig-to-W-implies-stable
[A:Type]. ((∀[B:A ⟶ Type]. ((¬¬(a:A × B[a])))  W(A;a.B[a])))  Stable{A})

Definition: wfd-tree
wfd-tree(T) ==  W(𝔹;z.if then Void else fi )

Lemma: wfd-tree_wf
[T:Type]. (wfd-tree(T) ∈ Type)

Definition: empty-wfd-tree
empty-wfd-tree(t) ==  wfd-tree-rec(tt;r.ff;t)

Lemma: wfd-tree-induction
[T:Type]
  ∀P:wfd-tree(T) ⟶ ℙ
    (P[Wsup(tt;⋅)]  (∀f:T ⟶ wfd-tree(T). ((∀b:T. P[f b])  P[Wsup(ff;f)]))  {∀t:wfd-tree(T). P[t]})

Definition: wfd-tree-rec
wfd-tree-rec(b;r.F[r];t) ==  W-rec(a,f,r.if then else F[r] fi ;t)

Lemma: wfd-tree-rec_wf
[X,T:Type]. ∀[b:X]. ∀[F:(T ⟶ X) ⟶ X]. ∀[t:wfd-tree(T)].  (wfd-tree-rec(b;r.F[r];t) ∈ X)

Lemma: wfd_tree_rec_node_lemma
F,f,F,b:Top.  (wfd-tree-rec(b;r.F[r];Wsup(ff;f)) F[λx.wfd-tree-rec(b;r.F[r];f x)])

Lemma: wfd_tree_rec_leaf_lemma
z,F,b:Top.  (wfd-tree-rec(b;x.F[x];Wsup(tt;z)) b)

Lemma: empty-wfd-tree_wf
[T:Type]. ∀[t:wfd-tree(T)].  (empty-wfd-tree(t) ∈ 𝔹)

Definition: stump
stump(t) ==  wfd-tree-rec(λn,s. ff;r.λn,s. if (n =z 0) then tt else (s 0) (n 1) i.(s (i 1))) fi ;t)

Lemma: stump_wf
[T:Type]. ∀[t:wfd-tree(T)].  (stump(t) ∈ n:ℕ ⟶ (ℕn ⟶ T) ⟶ 𝔹)

Lemma: stump-monotone
T:Type. ∀t:wfd-tree(T). ∀n:ℕ. ∀s:ℕn ⟶ T.  ((¬↑(stump(t) s))  (∀x:T. (¬↑(stump(t) (n 1) s++x))))

Lemma: stump-bars
T:Type. ∀t:wfd-tree(T). ∀alpha:ℕ ⟶ T.  ∃n:ℕ(¬↑(stump(t) alpha))

Lemma: stump-nil
T:Type. ∀t:wfd-tree(T). ∀s:ℕ0 ⟶ T.  (stump(t) ~ ¬bempty-wfd-tree(t))

Definition: stump'
stump'(t) ==  λn,s. if (n =z 0) then empty-wfd-tree(t) else b(stump(t) s)) ∧b (stump(t) (n 1) s) fi 

Lemma: stump'_wf
[T:Type]. ∀[t:wfd-tree(T)].  (stump'(t) ∈ n:ℕ ⟶ (ℕn ⟶ T) ⟶ 𝔹)

Lemma: stump'_property
T:Type. ∀t:wfd-tree(T). ∀n:ℕ. ∀s:ℕn ⟶ T.
  (↑(stump'(t) s) ⇐⇒ (¬↑(stump(t) s)) ∧ (0 <  (↑(stump(t) (n 1) s))))

Lemma: stump'-inductive
T:Type. ∀t:wfd-tree(T).
  (stump'(t)
  wfd-tree-rec(λn,s. (n =z 0);r.λn,s. if (n =z 0) then ff else (s 0) (n 1) i.(s (i 1))) fi ;t)
  ∈ (n:ℕ ⟶ (ℕn ⟶ T) ⟶ 𝔹))

Comment: accessibility
One way to define well-founded relation on type is to 
define inductively the accessible part of for an arbitrary relation R.
The is well-founded if every member of is accessible.

We can define accessible using type.
Then we can relate that inductive definition to the other
definitions of well-foundedness.⋅

Definition: accessible
accessible(T;x,y.R[x; y];t) ==  pW t

Lemma: accessible_wf
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ]. ∀[t:T].  (accessible(T;x,y.R[x;y];t) ∈ ℙ)

Lemma: accessible-iff
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ]. ∀[t:T].  (accessible(T;x,y.R[x;y];t) ⇐⇒ ∀u:T. (R[u;t]  accessible(T;x,y.R[x;y];u)))

Lemma: accessible-inversion
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ]. ∀[u:T].  ∀v:T. (accessible(T;x,y.R[x;y];u)  R[v;u]  accessible(T;x,y.R[x;y];v))

Lemma: accessible-induction
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ]. ∀[P:T ⟶ ℙ].
  ((∀t:T. ((∀x:T. (R[x;t]  P[x]))  P[t]))  (∀t:T. (accessible(T;x,y.R[x;y];t)  P[t])))

Lemma: all-accessible-iff-induction
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ].
  (∀t:T. accessible(T;x,y.R[x;y];t) ⇐⇒ ∀[P:T ⟶ ℙ]. ((∀t:T. ((∀x:T. (R[x;t]  P[x]))  P[t]))  (∀t:T. P[t])))

Lemma: all-accessible-iff-weak-TI
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ].  (∀t:T. accessible(T;x,y.R[x;y];t) ⇐⇒ ∀[P:T ⟶ ℙ]. weak-TI(T;x,y.R[y;x];t.P[t]))

Lemma: fix_wf_corec1
[F,H:Type ⟶ Type].
  ∀[G:⋂T:{T:Type| (F[T] ⊆T) ∧ (corec(T.F[T]) ⊆T)} (H[T] ⟶ H[F[T]]) ⋂ Top ⟶ H[Top]]. (fix(G) ∈ H[corec(T.F[T])]) 
  supposing Continuous(T.H[T]) ∧ Monotone(T.F[T])

Lemma: fix_wf_corec2'
[F,H:Type ⟶ Type].
  ∀[G:⋂T:{T:Type| corec(T.F[T]) ⊆T} (H[T] ⟶ H[F[T]]) ⋂ Top ⟶ H[Top]]. (fix(G) ∈ H[corec(T.F[T])]) 
  supposing Continuous(T.H[T])

Lemma: fix_wf_corec2
[F,H:Type ⟶ Type].
  ∀[G:⋂T:Type. (H[T] ⟶ H[F[T]]) ⋂ Top ⟶ H[Top]]. (fix(G) ∈ H[corec(T.F[T])]) supposing Continuous(T.H[T])

Lemma: fix_wf_corec
[F:Type ⟶ Type]. ∀[G:⋂T:Type. (T ⟶ F[T])].  (fix(G) ∈ corec(T.F[T]))

Lemma: fix_wf_corec_system
[F:Type ⟶ Type]
  ∀[I:Type]. ∀[G:⋂T:{T:Type| (F[T] ⊆T) ∧ (corec(T.F[T]) ⊆T)} ((I ⟶ T) ⟶ I ⟶ F[T])].
    (fix(G) ∈ I ⟶ corec(T.F[T])) 
  supposing Monotone(T.F[T])

Lemma: fix_wf_corec-alt-proof
[F:Type ⟶ Type]. ∀[G:⋂T:Type. (T ⟶ F[T])].  (fix(G) ∈ corec(T.F[T]))

Lemma: fix_wf_corec_parameter
[F:Type ⟶ Type]. ∀[A:Type]. ∀[G:Top ⟶ Top ⟶ Top ⋂ ⋂T:Type. ((A ⟶ T) ⟶ A ⟶ F[T])]. ∀[a:A].
  (fix(G) a ∈ corec(T.F[T]))

Lemma: fix_wf_corec_parameter2
[F,A:Type ⟶ Type].
  ∀[G:Top ⟶ Top ⟶ Top ⋂ ⋂T:Type. ((A[T] ⟶ T) ⟶ A[F[T]] ⟶ F[T])]. ∀[a:A[corec(T.F[T])]].
    (fix(G) a ∈ corec(T.F[T])) 
  supposing Continuous+(T.A[T])

Lemma: fix_wf_corec_parameter3
[F,A:Type ⟶ Type].
  ∀[G:Top ⟶ Top ⟶ Top ⋂ ⋂T:{T:Type| corec(T.F[T]) ⊆T} ((A[T] ⟶ T) ⟶ A[F[T]] ⟶ F[T])]. ∀[a:A[corec(T.F[T])]].
    (fix(G) a ∈ corec(T.F[T])) 
  supposing Continuous+(T.A[T])

Lemma: fix_wf_corec_3parameter
[F,A,B,C:Type ⟶ Type].
  (∀[G:Top ⟶ Top ⟶ Top ⟶ Top ⟶ Top ⋂ ⋂T:{T:Type| corec(T.F[T]) ⊆T} 
                                           ((A[T] ⟶ B[T] ⟶ C[T] ⟶ T) ⟶ A[F[T]] ⟶ B[F[T]] ⟶ C[F[T]] ⟶ F[T])].
   ∀[a:A[corec(T.F[T])]]. ∀[b:B[corec(T.F[T])]]. ∀[c:C[corec(T.F[T])]].
     (fix(G) c ∈ corec(T.F[T]))) supposing 
     (Continuous+(T.C[T]) and 
     Continuous+(T.B[T]) and 
     Continuous+(T.A[T]))

Definition: bar-base
bar-base(T) ==  corec(X.T X)

Lemma: bar-base_wf
[T:Type]. (bar-base(T) ∈ Type)

Lemma: bar-base-exteq
[T:Type]. bar-base(T) ≡ bar-base(T)

Lemma: bar-base-subtype
[T:Type]. (bar-base(T) ⊆(T bar-base(T)))

Lemma: bar-base_subtype
[T:Type]. ((T bar-base(T)) ⊆bar-base(T))

Definition: bar-val
bar-val(n;x) ==  fix((λbar-val,n,x. case of inl(b) => inr(z) => if (n =z 0) then inr ⋅  else bar-val (n 1) fi \000C)) x

Lemma: bar-val_wf
[n:ℕ]. ∀[T:Type]. ∀[x:bar-base(T)].  (bar-val(n;x) ∈ T?)

Lemma: bar-val-stable
[T:Type]. ∀[n:ℕ]. ∀[x:bar-base(T)].
  ∀[m:ℤ]. bar-val(m;x) bar-val(n;x) ∈ (T?) supposing n ≤ supposing ↑isl(bar-val(n;x))

Definition: diverge
diverge() ==  fix((λdiverge.(inr diverge )))

Lemma: diverge_wf
[T:Type]. (diverge() ∈ bar-base(T))

Lemma: bar-val-diverge
[T:Type]. ∀[n:ℕ].  (bar-val(n;diverge()) inr ⋅ )

Definition: in-bar
in-bar(b) ==  inl b

Lemma: in-bar_wf
[T:Type]. ∀[b:T].  (in-bar(b) ∈ bar-base(T))

Definition: bar-delay
bar-delay(b) ==  inr 

Lemma: bar-delay_wf
[T:Type]. ∀[x:bar-base(T)].  (bar-delay(x) ∈ bar-base(T))

Definition: bar-converges
x↓==  ∃n:ℕ(bar-val(n;x) (inl a) ∈ (T?))

Lemma: bar-converges_wf
[T:Type]. ∀[x:bar-base(T)]. ∀[a:T].  (x↓a ∈ ℙ)

Lemma: bar-converges-unique
[T:Type]. ∀[x:bar-base(T)]. ∀[a,b:T].  (x↓ x↓ (a b ∈ T))

Definition: bar-diverges
x↑ ==  ∀n:ℕ(¬↑isl(bar-val(n;x)))

Lemma: bar-diverges_wf
[T:Type]. ∀[x:bar-base(T)].  (x↑ ∈ ℙ)

Lemma: bar-converges-not-diverges
[T:Type]. ∀[x:bar-base(T)]. ∀[a:T].  (x↓ x↑))

Lemma: bar-diverges-iff
[T:Type]. ∀[x:bar-base(T)].  (x↑ ⇐⇒ ∀[a:T]. x↓a))

Definition: bar-equal
bar-equal(T;x;y) ==  ∀a:T. (x↓⇐⇒ y↓a)

Lemma: bar-equal_wf
[T:Type]. ∀[x,y:bar-base(T)].  (bar-equal(T;x;y) ∈ ℙ)

Lemma: bar-equal-equiv
[T:Type]. EquivRel(bar-base(T);x,y.bar-equal(T;x;y))

Lemma: bar-converges_functionality
[T:Type]. ∀[x,y:bar-base(T)]. ∀[a:T].  (bar-equal(T;x;y)  {x↓⇐⇒ x↓a})

Lemma: bar-diverges_functionality
[T:Type]. ∀[x,y:bar-base(T)].  (bar-equal(T;x;y)  {x↑ ⇐⇒ y↑})

Lemma: implies-bar-equal
[T:Type]. ∀x,y:bar-base(T).  (((∃a:T. (x↓a ∧ y↓a)) ∨ (x↑ ∧ y↑))  bar-equal(T;x;y))

Lemma: in-bar-converges
[T:Type]. ∀[b,a:T].  (in-bar(a)↓⇐⇒ b ∈ T)

Lemma: in-bar-equal
[T:Type]. ∀x:bar-base(T). ∀b:T.  (bar-equal(T;x;in-bar(b)) ⇐⇒ x↓b)

Lemma: bar-delay-equal
[T:Type]. ∀x:bar-base(T). bar-equal(T;x;bar-delay(x))

Definition: corecbar
corecbar(T) ==  x,y:bar-base(T)//bar-equal(T;x;y)

Lemma: corecbar_wf
[T:Type]. (corecbar(T) ∈ Type)

Definition: F-bisimulation
x,y.R[x; y] is an T.F[T]-bisimulation ==
  ∀T:Type
    (((F[T] ⊆T) ∧ (corec(T.F[T]) ⊆T))
     (∀x,y:corec(T.F[T]).  (R[x; y]  (x y ∈ T)))
     (∀x,y:corec(T.F[T]).  (R[x; y]  (x y ∈ F[T]))))

Lemma: F-bisimulation_wf
[F:Type ⟶ Type]. ∀[R:corec(T.F[T]) ⟶ corec(T.F[T]) ⟶ ℙ].
  x,y.R[x;y] is an T.F[T]-bisimulation ∈ ℙsupposing ContinuousMonotone(T.F[T])

Lemma: coinduction-principle
[F:Type ⟶ Type]
  ∀[R:corec(T.F[T]) ⟶ corec(T.F[T]) ⟶ ℙ]
    ∀[x,y:corec(T.F[T])].  y ∈ corec(T.F[T]) supposing R[x;y] supposing x,y.R[x;y] is an T.F[T]-bisimulation 
  supposing ContinuousMonotone(T.F[T])

Definition: indexed-F-bisimulation
x,y.R[x; y] is an T.F[T]-bisimulation (indexed I) ==
  ∀T:Type
    (((F[T] ⊆T) ∧ (corec(T.F[T]) ⊆T))
     (∀x,y:I ⟶ corec(T.F[T]).  (R[x; y]  (x y ∈ (I ⟶ T))))
     (∀x,y:I ⟶ corec(T.F[T]).  (R[x; y]  (x y ∈ (I ⟶ F[T])))))

Lemma: indexed-F-bisimulation_wf
[I:Type]. ∀[F:Type ⟶ Type]. ∀[R:(I ⟶ corec(T.F[T])) ⟶ (I ⟶ corec(T.F[T])) ⟶ ℙ].
  x,y.R[x;y] is an T.F[T]-bisimulation (indexed I) ∈ ℙsupposing ContinuousMonotone(T.F[T])

Lemma: indexed-coinduction-principle
[I:Type]. ∀[F:Type ⟶ Type].
  ∀[R:(I ⟶ corec(T.F[T])) ⟶ (I ⟶ corec(T.F[T])) ⟶ ℙ]
    ∀[x,y:I ⟶ corec(T.F[T])].  y ∈ (I ⟶ corec(T.F[T])) supposing R[x;y] 
    supposing x,y.R[x;y] is an T.F[T]-bisimulation (indexed I) 
  supposing ContinuousMonotone(T.F[T])

Definition: corec-rel
corec-rel(G) ==  λx,y. ∀n:ℕ(G^n x,y. True) y)

Lemma: corec-rel_wf
[F:Type ⟶ Type]
  ∀[G:⋂T:Type. ((T ⟶ T ⟶ ℙ) ⟶ F[T] ⟶ F[T] ⟶ ℙ)]. (corec-rel(G) ∈ corec(T.F[T]) ⟶ corec(T.F[T]) ⟶ ℙ
  supposing ContinuousMonotone(T.F[T])

Lemma: corec-rel-wf2
[F:𝕌' ⟶ 𝕌']
  ∀[G:⋂T:𝕌'. ((T ⟶ T ⟶ ℙ) ⟶ F[T] ⟶ F[T] ⟶ ℙ)]. (corec-rel(G) ∈ corec(T.F[T]) ⟶ corec(T.F[T]) ⟶ ℙ
  supposing continuous-monotone{i':l}(T.F[T])

Lemma: equiv-on-corec
F:Type ⟶ Type
  (ContinuousMonotone(T.F[T])
   (∀G:⋂T:Type. ((T ⟶ T ⟶ ℙ) ⟶ F[T] ⟶ F[T] ⟶ ℙ)
        ((∀T:Type. ∀E:T ⟶ T ⟶ ℙ.  (EquivRel(T;x,y.E y)  EquivRel(F[T];x,y.G y)))
         EquivRel(corec(T.F[T]);x,y.corec-rel(G) y))))

Lemma: equiv-on-corec-2
F:𝕌' ⟶ 𝕌'
  (continuous-monotone{i':l}(T.F[T])
   (∀G:⋂T:𝕌'. ((T ⟶ T ⟶ ℙ) ⟶ F[T] ⟶ F[T] ⟶ ℙ)
        ((∀T:𝕌'. ∀E:T ⟶ T ⟶ ℙ.  (EquivRel(T;x,y.E y)  EquivRel(F[T];x,y.G y)))
         EquivRel(corec(T.F[T]);x,y.corec-rel(G) y))))

Lemma: unique-corec-solution
[F:Type ⟶ Type]
  ∀[I:Type]
    ∀G:⋂T:{T:Type| (F[T] ⊆T) ∧ (corec(T.F[T]) ⊆T)} ((I ⟶ T) ⟶ I ⟶ F[T])
      ∃!s:I ⟶ corec(T.F[T]). (s (G s) ∈ (I ⟶ corec(T.F[T]))) 
  supposing ContinuousMonotone(T.F[T])

Lemma: corec_subtype
[F:Type ⟶ Type]. corec(T.F[T]) ⊆F[corec(T.F[T])] supposing Continuous(T.F[T])

Lemma: corec_subtype_base
[F:Type ⟶ Type]. corec(T.F[T]) ⊆Base supposing ∀n:ℕ. ∀T:Type.  (sqntype(n;T)  sqntype(n 1;F T))

Lemma: subtype_corec
[F:Type ⟶ Type]. F[corec(T.F[T])] ⊆corec(T.F[T]) supposing Monotone(T.F[T])

Lemma: subtype-corec1
[F:Type ⟶ Type]. ∀[T:Type]. T ⊆corec(T.F[T]) supposing T ⊆F[T] supposing Monotone(T.F[T])

Lemma: subtype-corec2
[A,B:Type ⟶ Type].
  (let corec(T.A[T] ⟶ B[T]) in P ⊆(A[P] ⟶ B[P])) supposing (Continuous+(T.B[T]) and Continuous+(T.A[T]))

Lemma: corec-subtype-corec2
[F,G:Type ⟶ Type].  corec(T.F[T]) ⊆corec(T.G[T]) supposing ∀A,B:Type.  ((A ⊆B)  (F[A] ⊆G[B]))

Lemma: corec-subtype-corec
[F,G:Type ⟶ Type].  (corec(T.F[T]) ⊆corec(T.G[T])) supposing (Monotone(T.G[T]) and (∀T:Type. (F[T] ⊆G[T])))

Comment: streams
simple example of using the co-induction principle on a
  co-recursive type.
  We will define infinite streams (of type A) in two different ways
  ⌜corec(S.A × S)⌝ and ⌜ℕ ⟶ A⌝ and show that there is bijection between them.

  And we will define some operators such as map on the corecursive stream type.
  
  We do an exercise from Pitts' lecture notes to show that 
          fibs() stream-map(λn.fib(n);nats()) ∈ stream(ℕ)
  
%⋅

Definition: stream
stream(A) ==  corec(S.A × S)

Lemma: stream_wf
[A:Type]. (stream(A) ∈ Type)

Lemma: stream-subtype
[A,B:Type].  stream(A) ⊆stream(B) supposing A ⊆B

Lemma: stream-ext
[A:Type]. stream(A) ≡ A × stream(A)

Lemma: stream_subtype_base
[T:Type]. stream(T) ⊆Base supposing T ⊆Base

Definition: s-hd
s-hd(s) ==  fst(s)

Lemma: s-hd_wf
[A:Type]. ∀[s:stream(A)].  (s-hd(s) ∈ A)

Definition: s-tl
s-tl(s) ==  snd(s)

Lemma: s-tl_wf
[A:Type]. ∀[s:stream(A)].  (s-tl(s) ∈ stream(A))

Definition: s-cons
x.s ==  <x, s>

Lemma: s-cons_wf
[A:Type]. ∀[x:A]. ∀[s:stream(A)].  (x.s ∈ stream(A))

Lemma: s_hd_cons_lemma
b,a:Top.  (s-hd(a.b) a)

Lemma: s_tl_cons_lemma
b,a:Top.  (s-tl(a.b) b)

Lemma: stream-decomp
[s:stream(Top)]. (s s-hd(s).s-tl(s))

Definition: s-nth
s-nth(n;s) ==  fix((λs-nth,n,s. let a,s' in if (n =z 0) then else eval in s-nth s' fi )) s

Lemma: s-nth_wf
[A:Type]. ∀[n:ℕ]. ∀[s:stream(A)].  (s-nth(n;s) ∈ A)

Lemma: stream-coinduction
[A:Type]. ∀[R:stream(A) ⟶ stream(A) ⟶ ℙ].
  ∀[x,y:stream(A)].  y ∈ stream(A) supposing 
  supposing ∀x,y:stream(A).  ((x y)  ((s-hd(x) s-hd(y) ∈ A) ∧ (s-tl(x) s-tl(y))))

Lemma: stream-extensionality
[A:Type]. ∀[x,y:stream(A)].  y ∈ stream(A) supposing ∀n:ℕ(s-nth(n;x) s-nth(n;y) ∈ A)

Definition: mk-stream
mk-stream(f;x) ==  fix((λmk-stream,x. <x, let y ⟵ in mk-stream y>)) x

Lemma: mk-stream_wf
[A:Type]. ∀[f:A ⟶ A]. ∀[x:A].  mk-stream(f;x) ∈ stream(A) supposing valueall-type(A)

Definition: const-stream
const-stream(x) ==  mk-stream(λz.x;x)

Lemma: const-stream_wf
[A:Type]. ∀[x:A].  const-stream(x) ∈ stream(A) supposing valueall-type(A)

Definition: stream-map
stream-map(f;s) ==  fix((λstream-map,s. let a,s' in <a, stream-map s'>)) s

Lemma: stream-map_wf
[A,B:Type]. ∀[f:A ⟶ B]. ∀[s:stream(A)].  (stream-map(f;s) ∈ stream(B))

Definition: stream-zip
stream-zip(f;as;bs) ==  fix((λstream-zip,as,bs. let a,as' as in let b,bs' bs in <b, stream-zip as' bs'>)) as bs

Lemma: stream-zip_wf
[A,B,C:Type]. ∀[f:A ⟶ B ⟶ C]. ∀[as:stream(A)]. ∀[bs:stream(B)].  (stream-zip(f;as;bs) ∈ stream(C))

Lemma: stream-zip_wf2
[A,B,C:Type]. ∀[f:A ⟶ B ⟶ C]. ∀[n:ℕ]. ∀[as:primrec(n;Top;λ,T. (A × T))]. ∀[bs:primrec(n;Top;λ,T. (B × T))].
  (stream-zip(f;as;bs) ∈ primrec(n;Top;λ,T. (C × T)))

Lemma: nth-stream-zip
[f:Top]. ∀[n:ℕ]. ∀[as,bs:stream(Top)].  (s-nth(n;stream-zip(f;as;bs)) s-nth(n;as) s-nth(n;bs))

Lemma: tl-stream-zip
[f:Top]. ∀[as,bs:stream(Top)].  (s-tl(stream-zip(f;as;bs)) stream-zip(f;s-tl(as);s-tl(bs)))

Lemma: hd-stream-zip
[f:Top]. ∀[as,bs:stream(Top)].  (s-hd(stream-zip(f;as;bs)) s-hd(as) s-hd(bs))

Lemma: nth-stream-map
[f:Top]. ∀[n:ℕ]. ∀[as:stream(Top)].  (s-nth(n;stream-map(f;as)) s-nth(n;as))

Definition: nats
nats() ==  mk-stream(λx.(x 1);0)

Lemma: nats_wf
nats() ∈ stream(ℕ)

Lemma: nth-nats
n:ℕ(s-nth(n;nats()) n)

Lemma: stream-bijection
[A:Type]. Bij(stream(A);ℕ ⟶ A;λs,n. s-nth(n;s))

Definition: stream-lex
stream-lex(T;R) ==  νlex.λs1,s2. ((s-hd(s1) s-hd(s2)) ∧ ((s-hd(s1) s-hd(s2) ∈ T)  (s-tl(s1) lex s-tl(s2))))

Lemma: stream-lex_wf
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ].  (stream-lex(T;R) ∈ stream(T) ⟶ stream(T) ⟶ ℙ)

Lemma: stream-lex-iff
T:Type. ∀R:T ⟶ T ⟶ ℙ. ∀s1,s2:stream(T).
  (s1 stream-lex(T;R) s2 ⇐⇒ (s-hd(s1) s-hd(s2)) ∧ ((s-hd(s1) s-hd(s2) ∈ T)  (s-tl(s1) stream-lex(T;R) s-tl(s2))))

Lemma: stream-lex_transitivity-proof2
T:Type. ∀R:T ⟶ T ⟶ ℙ.  (Trans(T;x,y.x y)  AntiSym(T;x,y.x y)  Trans(stream(T);s1,s2.s1 stream-lex(T;R) s2))

Lemma: stream-lex-monotonic
T:Type
  ((∀x,y:T.  Dec(x y ∈ T))
   (∀R:T ⟶ T ⟶ ℙ
        (Trans(T;x,y.x y)
         AntiSym(T;x,y.x y)
         (∀f:T ⟶ T ⟶ T
              ((∀x,y,u,v:T.  ((x y)  (u v)  ((f u) (f v))))
               (∀x,y,u,v:T.  ((x y)  (u v)  ((x y ∈ T) ∧ (u v ∈ T)))  ((f u) (f v) ∈ T))))
               (∀a,b,c,d:stream(T).
                    ((a stream-lex(T;R) b)
                     (c stream-lex(T;R) d)
                     (stream-zip(f;a;c) stream-lex(T;R) stream-zip(f;b;d)))))))))

Lemma: stream-lex_transitivity
T:Type. ∀R:T ⟶ T ⟶ ℙ.  (Trans(T;x,y.x y)  AntiSym(T;x,y.x y)  Trans(stream(T);s1,s2.s1 stream-lex(T;R) s2))

Definition: stream-pointwise
stream-pointwise(R) ==  νptwse.λs1,s2. ((s-hd(s1) s-hd(s2)) ∧ (s-tl(s1) ptwse s-tl(s2)))

Lemma: stream-pointwise_wf
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ].  (stream-pointwise(R) ∈ stream(T) ⟶ stream(T) ⟶ ℙ)

Lemma: stream-pointwise-iff
[T:Type]
  ∀R:T ⟶ T ⟶ ℙ. ∀s1,s2:stream(T).
    (s1 stream-pointwise(R) s2 ⇐⇒ (s-hd(s1) s-hd(s2)) ∧ (s-tl(s1) stream-pointwise(R) s-tl(s2)))

Lemma: stream-pointwise_transitivity
T:Type. ∀R:T ⟶ T ⟶ ℙ.  (Trans(T;x,y.x y)  Trans(stream(T);s1,s2.s1 stream-pointwise(R) s2))

Lemma: equal-zero-streams
fix((λx.<⋅x>)) fix((λx.<⋅, ⋅x>))

Definition: s-sub
s-sub(T;s;t) ==  ∃f:ℕ ⟶ ℕ((∀i:ℕi < (i 1)) ∧ (∀i:ℕ(s-nth(i;t) s-nth(f i;s) ∈ T)))

Lemma: s-sub_wf
[T:Type]. ∀[s,t:stream(T)].  (s-sub(T;s;t) ∈ ℙ)

Lemma: s-sub_transitivity
[T:Type]. ∀[s,t,r:stream(T)].  (s-sub(T;s;t)  s-sub(T;t;r)  s-sub(T;s;r))

Lemma: corec-subtype
[F:Type ⟶ Type]. corec(T.F[T]) ⊆F[corec(T.F[T])] supposing Continuous(T.F[T])

Definition: iterate-fun-stream
iterate-fun-stream(f;x) ==  fix((λiterate-fun-stream,x. x.iterate-fun-stream (f x))) x

Lemma: iterate-fun-stream_wf
[A:Type]. ∀[x:A]. ∀[f:A ⟶ A].  (iterate-fun-stream(f;x) ∈ stream(A))

Lemma: map-iterate-fun-stream
[f,x:Top].  (iterate-fun-stream(f;f x) stream-map(f;iterate-fun-stream(f;x)))

Lemma: fix-corec-partial1
[A:Type]
  (∀[F:Type ⟶ Type]. ∀[f:(corec(T.F[T]) ⟶ partial(A)) ⟶ corec(T.F[T]) ⟶ partial(A)].
     (fix(f) ∈ corec(T.F[T]) ⟶ partial(A))) supposing 
     (mono(A) and 
     value-type(A))

Lemma: fix_wf_corec-partial1
[A:Type]
  (∀[F:Type ⟶ Type]
     ∀[f:⋂T:Type. ((T ⟶ partial(A)) ⟶ F[T] ⟶ partial(A))]. (fix(f) ∈ corec(T.F[T]) ⟶ partial(A)) 
     supposing ContinuousMonotone(T.F[T])) supposing 
     (mono(A) and 
     value-type(A))

Lemma: fix_wf_corec_partial_nat
[F:Type ⟶ Type]
  ∀[f:⋂T:Type. ((T ⟶ partial(ℕ)) ⟶ F[T] ⟶ partial(ℕ))]. (fix(f) ∈ corec(T.F[T]) ⟶ partial(ℕ)) 
  supposing ContinuousMonotone(T.F[T])



Home Index