Lemma: no-repeats-iff-count
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].
  uiff(no_repeats(T;L);∀[x:T]. uiff(1 ≤ ||filter(eq x;L)||;||filter(eq x;L)|| 1 ∈ ℤ))

Lemma: sq-decider-list-deq
[eq:Base]. sq-decider(list-deq(eq)) supposing sq-decider(eq)

Lemma: deq-member-firstn
[A:Type]. ∀[eq:EqDecider(A)]. ∀[L:A List]. ∀[n:ℕ+].
  ∀[x:A]. (x ∈b firstn(n;L) x ∈b firstn(n 1;L) ∨b(eqof(eq) L[n 1])) supposing 1 < ||L||

Lemma: deq-member-length-filter
[A:Type]. ∀[eq:EqDecider(A)]. ∀[L:A List]. ∀[x:A].  (x ∈b 0 <||filter(λy.(eq x);L)||)

Lemma: deq-member-length-filter2
[A:Type]. ∀[eq:EqDecider(A)]. ∀[L:A List]. ∀[x:A].  (x ∈b 0 <||filter(λy.(eq y);L)||)

Lemma: l_member-iff-length-filter
[A:Type]. ∀eq:EqDecider(A). ∀L:A List. ∀x:A.  (1 ≤ ||filter(eq x;L)|| ⇐⇒ (x ∈ L))

Lemma: apply-alist-no_repeats
[A,T:Type]. ∀[eq:EqDecider(T)]. ∀[L:(T × A) List].
  ∀[x:T]. ∀[a:A].  apply-alist(eq;L;x) (inl a) ∈ (A?) supposing (<x, a> ∈ L) 
  supposing no_repeats(T;map(λp.(fst(p));L))

Lemma: no_repeats-update-alist
[A,T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[a:A]. ∀[f:A ⟶ A]. ∀[L:(T × A) List].
  no_repeats(T;map(λp.(fst(p));update-alist(eq;L;x;a;n.f[n]))) supposing no_repeats(T;map(λp.(fst(p));L))

Lemma: mapfilter-no-rep-fun
[T,U,V:Type]. ∀[eq:EqDecider(U)]. ∀[L:T List]. ∀[u:U]. ∀[f:T ⟶ U]. ∀[g:{x:{x:T| (x ∈ L)} | ↑(eq f[x] u)}  ⟶ V].
  ||mapfilter(g;λx.(eq f[x] u);L)|| ≤ supposing no_repeats(U;map(f;L))

Definition: possible-majority
possible-majority(T;eq;L;x) ==  ∀y:T. (||L|| < count(eq y;L)  (y x ∈ T))

Lemma: possible-majority_wf
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x:T.  (possible-majority(T;eq;L;x) ∈ ℙ)

Definition: poss-maj
poss-maj(eq;L;x) ==
  accumulate (with value and list item z):
   let n,x 
   in if eq then <1, x>
      if (n =z 0) then <1, z>
      else <1, x>
      fi 
  over list:
    L
  with starting value:
   <0, x>)

Lemma: poss-maj_wf
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x:T.  (poss-maj(eq;L;x) ∈ ℕ × T)

Lemma: poss-maj-invariant
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x:T.
  let n,z poss-maj(eq;L;x) 
  in ((count(eq z;L) count(λt.(¬b(eq t));L)) ≤ n)
     ∧ (∀y:T. ((¬↑(eq y))  (n ≤ (count(λt.(¬b(eq t));L) count(eq y;L)))))

Lemma: poss-maj-property
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x:T.  possible-majority(T;eq;L;snd(poss-maj(eq;L;x)))

Lemma: poss-maj-unanimous
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x,y:T.  ((poss-maj(eq;L;x) = <||L||, y> ∈ (ℕ × T))  (∀z∈L.z y ∈ T))

Lemma: poss-maj-member
T:Type. ∀eq:EqDecider(T). ∀L:T List. ∀x:T.  (snd(poss-maj(eq;L;x)) ∈ [x L])

Lemma: poss-maj-length
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[x:T].  ((fst(poss-maj(eq;L;x))) ≤ ||L||)

Lemma: poss-maj-length2
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[x:T]. ∀[n:ℤ].  n ≤ ||L|| supposing (fst(poss-maj(eq;L;x))) n ∈ ℤ

Lemma: map-simplify-test
[H,f,g:Base]. ∀[L:Atom List].  (map(λx.H[if x ∈b then f[x] else g[x] fi ];L) map(λx.H[f[x]];L))

Definition: weak-update-alist
weak-update-alist(eq;L;x;z;v.f[v]) ==  update-alist(eq;L;x;z;v.f[v])

Lemma: weak-update-alist_wf
[A,T:Type]. ∀[eq:T ⟶ T ⟶ 𝔹]. ∀[x:T]. ∀[L:(T × A) List]. ∀[z:A]. ∀[f:A ⟶ A].
  (weak-update-alist(eq;L;x;z;v.f[v]) ∈ (T × A) List)

Definition: remove-alist
remove-alist(eq;L;x) ==  rec-case(L) of [] => [] p::ps => r.let a,v in if eq then else [p r] fi 

Lemma: remove-alist_wf
[A,T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[L:(T × A) List].  (remove-alist(eq;L;x) ∈ (T × A) List)

Definition: count-repeats
count-repeats(L,eq) ==
  accumulate (with value cvs and list item v):
   update-alist(eq;cvs;v;1;n.n 1)
  over list:
    L
  with starting value:
   [])

Lemma: count-repeats_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (count-repeats(L,eq) ∈ (T × ℕ+List)

Lemma: no_repeats-count-repeats1
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  no_repeats(T;map(λp.(fst(p));count-repeats(L,eq)))

Lemma: apply-alist-count-repeats
[T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[L:T List].
  (apply-alist(eq;count-repeats(L,eq);x) if x ∈b then inl ||filter(λy.(eq x);L)|| else inr ⋅  fi  ∈ (ℕ+?))

Lemma: member-count-repeats1
[T:Type]. ∀eq:EqDecider(T). ∀x:T. ∀L:T List.  ((x ∈ map(λp.(fst(p));count-repeats(L,eq))) ⇐⇒ (x ∈ L))

Lemma: member-count-repeats2
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List. ∀i:ℕ||count-repeats(L,eq)||.
    let x,n count-repeats(L,eq)[i] 
    in ||filter(λy.(eq x);L)|| ∈ ℤ

Lemma: member-count-repeats3
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[x:T]. ∀[n:ℕ+].
  ||filter(λy.(eq x);L)|| ∈ ℤ supposing (<x, n> ∈ count-repeats(L,eq))

Lemma: sum-count-repeats
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (snd(count-repeats(L,eq)[i]) i < ||count-repeats(L,eq)||) ||L|| ∈ ℤ)

Definition: strict-majority
strict-majority(eq;L) ==
  let ms filter(λp.||L|| <(snd(p));count-repeats(L,eq)) in
      if null(ms) then inr ⋅  else inl (fst(hd(ms))) fi 

Lemma: strict-majority_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (strict-majority(eq;L) ∈ T?)

Lemma: strict-majority-property
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[x:T].
  uiff(||L|| < ||filter(λy.(eq x);L)||;strict-majority(eq;L) (inl x) ∈ (T?))

Lemma: strict-majority_functionality
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].
  (strict-majority(eq;L1) strict-majority(eq;L2) ∈ (T?)) supposing 
     ((||L1|| ||L2|| ∈ ℤand 
     (∀x:T. (||filter(λy.(eq x);L1)|| ||filter(λy.(eq x);L2)|| ∈ ℤ)))

Definition: strict-majority-or-first
strict-majority-or-first(eq;L) ==  case strict-majority(eq;L) of inl(x) => inr(z) => hd(L)

Lemma: strict-majority-or-first_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:{L:T List| ||L|| ≥ ].  (strict-majority-or-first(eq;L) ∈ T)

Definition: strict-majority-or-max
strict-majority-or-max(L) ==
  case strict-majority(IntDeq;L) of inl(x) => inr(z) => if null(L) then else imax-list(L) fi 

Lemma: strict-majority-or-max_wf
[L:ℤ List]. (strict-majority-or-max(L) ∈ ℤ)

Lemma: strict-majority-or-max-property
t:ℕ. ∀L:ℤ List.
  ((∀v:ℤ
      (strict-majority-or-max(L) v ∈ ℤsupposing 
         (((t 1) ≤ ||filter(λx.(x =z v);L)||) and 
         (||L|| ((2 t) 1) ∈ ℤ)))
  ∧ (strict-majority-or-max(L) ∈ L) supposing ||L|| ≥ )

Definition: deq-disjoint
deq-disjoint(eq;as;bs) ==  (∀a∈as.¬ba ∈b bs)_b

Lemma: deq-disjoint_wf
[A:Type]. ∀[eq:EqDecider(A)]. ∀[as,bs:A List].  (deq-disjoint(eq;as;bs) ∈ 𝔹)

Lemma: assert-deq-disjoint
[A:Type]. ∀[eq:EqDecider(A)]. ∀[as,bs:A List].  uiff(↑deq-disjoint(eq;as;bs);l_disjoint(A;as;bs))

Definition: deq-all-disjoint
deq-all-disjoint(eq;ass;bs) ==  (∀as∈ass.deq-disjoint(eq;as;bs))_b

Lemma: deq-all-disjoint_wf
[A:Type]. ∀[eq:EqDecider(A)]. ∀[ass:A List List]. ∀[bs:A List].  (deq-all-disjoint(eq;ass;bs) ∈ 𝔹)

Lemma: assert-deq-all-disjoint
[A:Type]. ∀[eq:EqDecider(A)]. ∀[ass:A List List]. ∀[bs:A List].
  uiff(↑deq-all-disjoint(eq;ass;bs);(∀as∈ass.l_disjoint(A;as;bs)))

Definition: discrete_struct
DS(A) ==  sort:A ⟶ Type × (a:A ⟶ EqDecider(sort a))

Lemma: discrete_struct_wf
[A:Type]. (DS(A) ∈ 𝕌')

Definition: dstype
dstype(TypeNames; d; a) ==  (fst(d)) a

Lemma: dstype_wf
[TypeNames:Type]. ∀[d:DS(TypeNames)]. ∀[a:TypeNames].  (dstype(TypeNames; d; a) ∈ Type)

Lemma: decidable__dstype_equal
[A:Type]. ∀a:A. ∀d:DS(A). ∀x,y:dstype(A; d; a).  Dec(x y ∈ dstype(A; d; a))

Definition: dsdeq
dsdeq(d;a) ==  (snd(d)) a

Lemma: dsdeq_wf
[A:Type]. ∀[d:DS(A)]. ∀[a:A].  (dsdeq(d;a) ∈ EqDecider(dstype(A; d; a)))

Definition: dseq
dseq(d;a) ==  (snd(d)) a

Lemma: dseq_wf
[TypeNames:Type]. ∀[d:DS(TypeNames)]. ∀[a:TypeNames].
  (dseq(d;a) ∈ dstype(TypeNames; d; a) ⟶ dstype(TypeNames; d; a) ⟶ 𝔹)

Definition: eq_ds
==  dseq(d;a) y

Lemma: eq_ds_wf
[A:Type]. ∀[d:DS(A)]. ∀[a:A]. ∀[x,y:dstype(A; d; a)].  (x y ∈ 𝔹)

Lemma: ds_property
[A:Type]. ∀[d:DS(A)]. ∀[a:A]. ∀[x,y:dstype(A; d; a)].  {uiff(x y ∈ dstype(A; d; a);↑y)}

Definition: l-union'
l-union'(eq; as; bs) ==  cbv_list_accum(L,x.if x ∈b then else [x L] fi ;as;bs)

Lemma: l-union-nil
[eq,as:Top].  (as ⋃ [] as)

Lemma: filter-union
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List. ∀P:T ⟶ 𝔹.  (filter(P;as ⋃ bs) filter(P;as) ⋃ filter(P;bs) ∈ (T List))

Lemma: l-union-subset
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  as ⋃ bs as supposing bs ⊆ as

Lemma: l-union-same
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as:T List].  (as ⋃ as as)

Lemma: l-union_functionality_wrt-l_contains
[T:Type]. ∀eq:EqDecider(T). ∀as1,bs1,as2,bs2:T List.  (bs1 ⊆ bs2  as1 ⊆ as2  as1 ⋃ bs1 ⊆ as2 ⋃ bs2)

Lemma: l-union-contained
[T:Type]. ∀eq:EqDecider(T). ∀as,bs,cs:T List.  (as ⋃ bs ⊆ cs ⇐⇒ as ⊆ cs ∧ bs ⊆ cs)

Lemma: l-union-left-contains
[T:Type]. ∀eq:EqDecider(T). ∀as,bs,cs:T List.  (as ⊆ bs  as ⊆ bs ⋃ cs)

Lemma: l-union-right-contains
[T:Type]. ∀eq:EqDecider(T). ∀as,bs,cs:T List.  (as ⊆ cs  as ⊆ bs ⋃ cs)

Lemma: map-l-union
[T,T':Type]. ∀[f:T ⟶ T']. ∀[eq:EqDecider(T)]. ∀[eq':EqDecider(T')]. ∀[as,bs:T List].
  map(f;as ⋃ bs) map(f;as) ⋃ map(f;bs) supposing Inj({x:T| (x ∈ as ⋃ bs)} ;T';f)

Lemma: map-l-union-1
[T:Type]. ∀[f:T ⟶ T]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].
  map(f;as ⋃ bs) map(f;as) ⋃ map(f;bs) supposing Inj({x:T| (x ∈ as ⋃ bs)} ;T;f)

Lemma: deq-member-union
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List]. ∀[x:T].  (x ∈b as ⋃ bs x ∈b as ∨bx ∈b bs)

Lemma: union-contains
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List.  as ⊆ as ⋃ bs

Lemma: union-contains2
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List.  bs ⊆ as ⋃ bs

Lemma: no_repeats_union
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  no_repeats(T;as ⋃ bs) supposing no_repeats(T;as)

Lemma: no_repeats-union-list
[T:Type]. ∀[eq:EqDecider(T)]. ∀[ll:T List List].  no_repeats(T;l-union-list(eq;ll))

Definition: val-union
val-union(eq;as;bs) ==  let as ⟵ as in let bs ⟵ bs in reduce(λa,L. insert(a;L);as;bs)

Lemma: val-union_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  val-union(eq;as;bs) ∈ List supposing valueall-type(T)

Lemma: val-union-l-union
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  val-union(eq;as;bs) as ⋃ bs supposing valueall-type(T)

Definition: union-list2
union-list2(eq;ll) ==  rec-case(ll) of [] => [] l1::l2 => r.if null(l2) then l1 else r ⋃ l1 fi 

Lemma: union-list2_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[ll:T List List].  (union-list2(eq;ll) ∈ List)

Lemma: member-union-list2
[T:Type]. ∀eq:EqDecider(T). ∀ll:T List List. ∀x:T.  ((x ∈ union-list2(eq;ll)) ⇐⇒ ∃l:T List. ((l ∈ ll) ∧ (x ∈ l)))

Lemma: union-list2-simplify1
[T:Type]. ∀[eq:EqDecider(T)]. ∀[ll:T List List]. ∀[L:T List].
  (union-list2(eq;[L; [L ll]]) union-list2(eq;[L ll]))

Definition: no_rel_repeats
no_rel_repeats(T;R;l) ==  ∀i,j:ℕ.  (i < ||l||  j < ||l||  (i j ∈ ℕ))  (R l[i] l[j])))

Lemma: no_rel_repeats_wf
[T:Type]. ∀[R:T ⟶ T ⟶ ℙ]. ∀[l:T List].  (no_rel_repeats(T;R;l) ∈ ℙ)

Definition: list-to-set
list-to-set(eq;L) ==  [] ⋃ L

Lemma: list-to-set_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (list-to-set(eq;L) ∈ List)

Lemma: list-to-set-property
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List.  (no_repeats(T;list-to-set(eq;L)) ∧ (∀a:T. ((a ∈ list-to-set(eq;L)) ⇐⇒ (a ∈ L))))

Lemma: member-list-to-set
[T:Type]. ∀eq:EqDecider(T). ∀L:T List. ∀a:T.  ((a ∈ list-to-set(eq;L)) ⇐⇒ (a ∈ L))

Lemma: list_to_set_nil_lemma
eq:Top. (list-to-set(eq;[]) [])

Lemma: list-to-set-cons
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List. ∀a:T.
    (list-to-set(eq;[a L]) if a ∈b list-to-set(eq;L) then list-to-set(eq;L) else [a list-to-set(eq;L)] fi )

Lemma: no-repeats-list-to-set
[T:Type]. ∀eq:EqDecider(T). ∀L:T List.  list-to-set(eq;L) supposing no_repeats(T;L)

Lemma: list-to-set-filter
[T:Type]. ∀eq:EqDecider(T). ∀P:T ⟶ 𝔹. ∀L:T List.  (list-to-set(eq;filter(P;L)) filter(P;list-to-set(eq;L)))

Definition: remove-repeats
remove-repeats(eq;L) ==  rec-case(L) of [] => [] a::as => r.[a filter(λx.(¬b(eq a));r)]

Lemma: remove-repeats_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (remove-repeats(eq;L) ∈ List)

Lemma: remove-repeats_property
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List.  (no_repeats(T;remove-repeats(eq;L)) ∧ (∀a:T. ((a ∈ remove-repeats(eq;L)) ⇐⇒ (a ∈ L))))

Lemma: set-equal-remove-repeats
[T:Type]. ∀eq:EqDecider(T). ∀L:T List.  set-equal(T;remove-repeats(eq;L);L)

Lemma: member-remove-repeats
[T:Type]. ∀eq:EqDecider(T). ∀L:T List. ∀a:T.  ((a ∈ remove-repeats(eq;L)) ⇐⇒ (a ∈ L))

Lemma: remove-repeats-set-equal
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].
  ||remove-repeats(eq;L1)|| ||remove-repeats(eq;L2)|| ∈ ℤ supposing set-equal(T;L1;L2)

Lemma: remove-repeats-l_contains
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].  ||remove-repeats(eq;L1)|| ≤ ||remove-repeats(eq;L2)|| supposing L1 ⊆ L2

Lemma: remove-repeats-l_contains-iff
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List.  (as ⊆ bs ⇐⇒ remove-repeats(eq;as) ⊆ remove-repeats(eq;bs))

Lemma: l_all-remove-repeats
[T:Type]. ∀eq:EqDecider(T). ∀L:T List. ∀P:{x:T| (x ∈ L)}  ⟶ ℙ.  ((∀x∈remove-repeats(eq;L).P[x]) ⇐⇒ (∀x∈L.P[x]))

Lemma: remove-repeats-append
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].  (||remove-repeats(eq;L1 L2)|| ||remove-repeats(eq;L2 L1)|| ∈ ℤ)

Lemma: remove-repeats-append-sq
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].
  (remove-repeats(eq;L1 L2) remove-repeats(eq;L1) filter(λx.(¬bx ∈b L1);remove-repeats(eq;L2)))

Lemma: remove-repeats-append-one
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List. ∀x:T.
    ((||remove-repeats(eq;L [x])|| ||remove-repeats(eq;L)|| ∈ ℤ)
    ∨ (||remove-repeats(eq;L [x])|| (||remove-repeats(eq;L)|| 1) ∈ ℤ))

Lemma: remove-repeats-append-one-member
[T:Type]
  ∀eq:EqDecider(T). ∀L:T List. ∀x:T.
    (((x ∈ L) ∧ (||remove-repeats(eq;L [x])|| ||remove-repeats(eq;L)|| ∈ ℤ))
    ∨ ((¬(x ∈ L)) ∧ (||remove-repeats(eq;L [x])|| (||remove-repeats(eq;L)|| 1) ∈ ℤ)))

Lemma: remove_repeats_cons_lemma
v,u,eq:Top.  (remove-repeats(eq;[u v]) [u filter(λx.(¬b(eq u));remove-repeats(eq;v))])

Lemma: remove_repeats_nil_lemma
eq:Top. (remove-repeats(eq;[]) [])

Lemma: length-remove-repeats
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L1,L2:T List].
  ||remove-repeats(eq;L1)|| ||remove-repeats(eq;L2)|| ∈ ℤ supposing ∀x:T. ((x ∈ L1) ⇐⇒ (x ∈ L2))

Lemma: length-remove-repeats-le
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (||remove-repeats(eq;L)|| ≤ ||L||)

Lemma: remove-repeats-filter
[T:Type]. ∀[eq:EqDecider(T)]. ∀[P:T ⟶ 𝔹]. ∀[L:T List].
  (remove-repeats(eq;filter(P;L)) filter(P;remove-repeats(eq;L)) ∈ (T List))

Lemma: remove-repeats-no_repeats
T:Type. ∀eq:EqDecider(T). ∀L:T List.  no_repeats(T;remove-repeats(eq;L))

Lemma: remove-repeats-no_repeats-true
T:Type. ∀eq:EqDecider(T). ∀L:T List.  (no_repeats(T;remove-repeats(eq;L)) ⇐⇒ True)

Lemma: remove-repeats_functionality_wrt_permutation
[T:Type]
  ∀eq:EqDecider(T). ∀L1,L2:T List.  (permutation(T;L1;L2)  permutation(T;remove-repeats(eq;L1);remove-repeats(eq;L2)))

Lemma: remove-repeats-length-one
T:Type. ∀eq:EqDecider(T). ∀L:T List.
  (||remove-repeats(eq;L)|| 1 ∈ ℤ ⇐⇒ ∃x:T. ((x ∈ L) ∧ (∀y:T. x ∈ supposing (y ∈ L))))

Lemma: permutation-iff-count1
[T:Type]
  ∀eq:T ⟶ T ⟶ 𝔹
    ((∀x,y:T.  (↑(eq y) ⇐⇒ y ∈ T))
     (∀a1,b1:T List.  (∀x:T. (||filter(eq x;a1)|| ||filter(eq x;b1)|| ∈ ℤ⇐⇒ permutation(T;a1;b1))))

Lemma: list-to-set_functionality_wrt_permutation
[T:Type]
  ∀eq:EqDecider(T). ∀L1,L2:T List.  (permutation(T;L1;L2)  permutation(T;list-to-set(eq;L1);list-to-set(eq;L2)))

Lemma: list-to-set-is-remove-repeats
[T:Type]. ∀eq:EqDecider(T). ∀L:T List.  permutation(T;list-to-set(eq;L);remove-repeats(eq;L))

Definition: values-for-distinct
values-for-distinct(eq;L) ==  map(λa.outl(apply-alist(eq;L;a));remove-repeats(eq;map(λp.(fst(p));L)))

Lemma: values-for-distinct_wf
[A,V:Type]. ∀[eq:EqDecider(A)]. ∀[L:(A × V) List].  (values-for-distinct(eq;L) ∈ List)

Lemma: values-for-distinct-property
[A,V:Type].
  ∀eq:EqDecider(A). ∀L:(A × V) List.
    ((||values-for-distinct(eq;L)|| ||remove-repeats(eq;map(λp.(fst(p));L))|| ∈ ℤ)
    ∧ (∀i:ℕ||remove-repeats(eq;map(λp.(fst(p));L))||
         (<remove-repeats(eq;map(λp.(fst(p));L))[i], values-for-distinct(eq;L)[i]> ∈ L)))

Lemma: values-for-distinct-nil
[A,V:Type]. ∀[eq:EqDecider(A)]. ∀[L:(A × V) List].
  uiff(values-for-distinct(eq;L) [] ∈ (V List);L [] ∈ ((A × V) List))

Lemma: member-values-for-distinct
[A,V:Type].
  ∀eq:EqDecider(A). ∀L:(A × V) List. ∀a:A.
    ((a ∈ map(λp.(fst(p));L))  (∃v:V. ((v ∈ values-for-distinct(eq;L)) ∧ (<a, v> ∈ L))))

Lemma: member-values-for-distinct2
[A,V:Type].  ∀eq:EqDecider(A). ∀L:(A × V) List. ∀v:V.  ((v ∈ values-for-distinct(eq;L))  (∃a:A. (<a, v> ∈ L)))

Lemma: list_accum-remove-repeats
[T:Type]. ∀[eq:EqDecider(T)]. ∀[A:Type]. ∀[g:T ⟶ A]. ∀[f:A ⟶ A ⟶ A].
  (∀[as:T List]. ∀[n:A].
     (accumulate (with value and list item z):
       f[a;g[z]]
      over list:
        as
      with starting value:
       n)
     accumulate (with value and list item z):
        f[a;g[z]]
       over list:
         remove-repeats(eq;as)
       with starting value:
        n)
     ∈ A)) supposing 
     ((∀x:A. (f[x;x] x ∈ A)) and 
     Assoc(A;λx,y. f[x;y]) and 
     Comm(A;λx,y. f[x;y]))

Lemma: list_accum-set-equal-idemp
[T:Type]. ∀[eq:EqDecider(T)]. ∀[A:Type]. ∀[g:T ⟶ A]. ∀[f:A ⟶ A ⟶ A].
  (∀[as,bs:T List].
     ∀[n:A]
       (accumulate (with value and list item z):
         f[a;g[z]]
        over list:
          as
        with starting value:
         n)
       accumulate (with value and list item z):
          f[a;g[z]]
         over list:
           bs
         with starting value:
          n)
       ∈ A) 
     supposing set-equal(T;as;bs)) supposing 
     ((∀x:A. (f[x;x] x ∈ A)) and 
     Assoc(A;λx,y. f[x;y]) and 
     Comm(A;λx,y. f[x;y]))

Definition: remove-repeats-fun
remove-repeats-fun(eq;f;L) ==  rec-case(L) of [] => [] a::as => r.[a filter(λx.(¬b(eq (f x) (f a)));r)]

Lemma: remove-repeats-fun_wf
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[f:A ⟶ B]. ∀[L:A List].  (remove-repeats-fun(eq;f;L) ∈ List)

Lemma: remove-repeats-fun-nil
[eq,f:Top].  (remove-repeats-fun(eq;f;[]) [])

Lemma: remove-repeats-fun-as-remove-repeats-map
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[f:A ⟶ B]. ∀[L:A List].
  (map(f;remove-repeats-fun(eq;f;L)) remove-repeats(eq;map(f;L)) ∈ (B List))

Lemma: remove-repeats-fun-length-as-remove-repeats-map
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[f:A ⟶ B]. ∀[L:A List].
  (||remove-repeats-fun(eq;f;L)|| ||remove-repeats(eq;map(f;L))|| ∈ ℤ)

Lemma: remove-repeats-fun-sublist
[A,B:Type].  ∀eq:EqDecider(B). ∀f:A ⟶ B. ∀L:A List.  remove-repeats-fun(eq;f;L) ⊆ L

Lemma: remove-repeats-fun-member
[A,B:Type].
  ∀eq:EqDecider(B). ∀f:A ⟶ B. ∀L:A List. ∀a:A.
    ((a ∈ remove-repeats-fun(eq;f;L)) ⇐⇒ ∃i:ℕ||L||. ((L[i] a ∈ A) ∧ (∀j:ℕi. ((f L[j]) (f a) ∈ B)))))

Lemma: remove-repeats-fun-map
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[f:A ⟶ B]. ∀[L:A List].
  (map(f;remove-repeats-fun(eq;f;L)) remove-repeats(eq;map(f;L)) ∈ (B List))

Lemma: remove-repeats-fun-map2
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[L:A List]. ∀[f:{a:A| (a ∈ L)}  ⟶ B].
  (map(f;remove-repeats-fun(eq;f;L)) remove-repeats(eq;map(f;L)) ∈ (B List))

Lemma: remove-repeats-fun-as-filter
[A,B:Type]. ∀[eq:EqDecider(B)]. ∀[f:A ⟶ B]. ∀[R:A ⟶ A ⟶ 𝔹]. ∀[L:A List].
  (remove-repeats-fun(eq;f;L) filter(λa.(¬b(∃x∈L.R[x;a] ∧b (eq (f x) (f a)))_b);L)) supposing 
     (sorted-by(λx,y. (↑R[x;y]);L) and 
     StAntiSym(A;x,y.↑R[x;y]) and 
     Irrefl(A;x,y.↑R[x;y]))

Lemma: remove-repeats-mapfilter-with-fun
[T,U:Type]. ∀[eq:EqDecider(U)]. ∀[R:T ⟶ T ⟶ 𝔹]. ∀[L:T List]. ∀[P:T ⟶ 𝔹]. ∀[f:{x:T| ↑(P x)}  ⟶ U].
  (remove-repeats(eq;mapfilter(f;P;L))
     mapfilter(f;λa.((P a) ∧b b(∃x∈L.(P x) ∧b R[x;a] ∧b (eq (f x) (f a)))_b));L)
     ∈ (U List)) supposing 
     (sorted-by(λx,y. (↑R[x;y]);L) and 
     StAntiSym(T;x,y.↑R[x;y]) and 
     Irrefl(T;x,y.↑R[x;y]))

Lemma: remove-repeats-length-no-repeats
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  ||remove-repeats(eq;L)|| ||L|| ∈ ℤ supposing no_repeats(T;L)

Lemma: remove-repeats-length-leq
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  (||remove-repeats(eq;L)|| ≤ ||L||)

Lemma: remove-repeats-length-no-repeats-iff
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  uiff(no_repeats(T;L);||remove-repeats(eq;L)|| ||L|| ∈ ℤ)

Definition: l_eqset
l_eqset(T;L1;L2) ==  ∀x:T. ((x ∈ L1) ⇐⇒ (x ∈ L2))

Lemma: l_eqset_wf
[T:Type]. ∀[L1,L2:T List].  (l_eqset(T;L1;L2) ∈ ℙ)

Lemma: l_contains-eq_set-no_repeats
[T:Type]. ∀[as,bs:T List]. ∀[eq:EqDecider(T)].
  (no_repeats(T;as)) supposing (l_eqset(T;as;bs) and no_repeats(T;bs) and (||as|| ||bs|| ∈ ℤ))

Definition: list-diff
as-bs ==  filter(λa.(¬ba ∈b bs);as)

Lemma: list-diff_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  (as-bs ∈ List)

Lemma: list-diff-cons
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List]. ∀[x:T].
  ([x as]-bs if x ∈b bs then as-bs else [x as-bs] fi  ∈ (T List))

Lemma: list-diff-cons-single
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as:T List]. ∀[b,x:T].  [x as]-[b] [x as-[b]] ∈ (T List) supposing ¬(x b ∈ T)

Lemma: list-diff_functionality
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs,cs:T List].
  as-bs as-cs ∈ (T List) supposing ∀x:T. ((x ∈ as)  ((x ∈ bs) ⇐⇒ (x ∈ cs)))

Lemma: list-diff-property
[T:Type]
  ∀eq:EqDecider(T). ∀as,bs:T List.
    ((∀x:T. ((x ∈ as-bs) ⇐⇒ (x ∈ as) ∧ (x ∈ bs)))) ∧ no_repeats(T;as-bs) supposing no_repeats(T;as))

Lemma: list-diff-subset
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List.  l_subset(T;as-bs;as)

Lemma: member-list-diff
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List. ∀x:T.  ((x ∈ as-bs) ⇐⇒ (x ∈ as) ∧ (x ∈ bs)))

Lemma: list-diff-diff
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs,cs:T List].  (as-bs-cs as-bs cs ∈ (T List))

Lemma: list-diff2
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as:T List]. ∀[b,c:T].  (as-[b; c] as-[b]-[c] ∈ (T List))

Lemma: list-diff2-sym
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as:T List]. ∀[b,c:T].  (as-[b; c] as-[c]-[b] ∈ (T List))

Lemma: list-diff-disjoint
[T:Type]. ∀[eq:EqDecider(T)]. ∀[as,bs:T List].  as-bs as ∈ (T List) supposing l_disjoint(T;as;bs)

Lemma: length-list-diff
[T:Type]. ∀eq:EqDecider(T). ∀as,bs:T List.  ((||as-bs|| ≤ ||as||) ∧ ||as-bs|| < ||as|| supposing (∃a∈as. (a ∈ bs)))

Lemma: no_repeats_list-diff
[T:Type]. ∀[L1,L2:T List]. ∀[eq:EqDecider(T)].  no_repeats(T;L1-L2) supposing no_repeats(T;L1)

Lemma: filter-list-diff
[T:Type]. ∀[P:T ⟶ 𝔹]. ∀[L1,L2:T List]. ∀[eq:EqDecider(T)].  (filter(P;L1-L2) filter(P;L1)-filter(P;L2))

Definition: list-index
list-index(d;L;x) ==
  rec-case(L) of
  [] => inr ⋅ 
  z::L' =>
   r.case of inl(n) => inl (n 1) inr(a) => if eqof(d) then inl else fi 

Lemma: list-index_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[L:T List].  (list-index(eq;L;x) ∈ ℕ||L|| Top)

Lemma: isl-list-index
[T:Type]. ∀eq:EqDecider(T). ∀x:T. ∀L:T List.  (↑isl(list-index(eq;L;x)) ⇐⇒ (x ∈ L))

Lemma: list-index-property
[T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[L:T List].  L[outl(list-index(eq;L;x))] x ∈ supposing (x ∈ L)

Definition: list-index-cmp
list-index-cmp(eq;L;f) ==  int-minus-comparison(λx.outl(list-index(eq;L;f x)))

Lemma: list-index-cmp_wf
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[A:Type]. ∀[f:A ⟶ T].
  (list-index-cmp(eq;L;f) ∈ comparison({x:A| (f x ∈ L)} ))

Lemma: list-index-cmp-zero
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[A:Type]. ∀[f:A ⟶ T]. ∀[x,y:{x:A| (f x ∈ L)} ].
  uiff((list-index-cmp(eq;L;f) y) 0 ∈ ℤ;(f x) (f y) ∈ T)

Lemma: assert-exists-l_subset
[T:Type]
  ((∀x,y:T.  Dec(x y ∈ T))
   (∀P:(T List) ⟶ 𝔹
        ((∀L1,L2:T List.  (set-equal(T;L1;L2)  (↑(P L1) ⇐⇒ ↑(P L2))))
         (∀L:T List. (↑exists_sublist(L;P) ⇐⇒ ∃LL:T List. (l_subset(T;LL;L) ∧ (↑(P LL))))))))

Definition: round-robin
round-robin(L) ==  λn.L[n rem ||L||]

Lemma: round-robin_wf
[T:Type]. ∀[L:T List].  round-robin(L) ∈ ℕ ⟶ supposing 0 < ||L||

Lemma: round-robin-member
[T:Type]. ∀L:T List. ∀n:ℕ(round-robin(L) n ∈ L) supposing 0 < ||L||

Lemma: round-robin-onto
[T:Type]. ∀L:T List. (∀x∈L.∃b:ℕ(x (round-robin(L) b) ∈ T))

Lemma: round-robin-equal
[L:Top List]. ∀[b:ℕ]. (round-robin(L) (b ||L||) round-robin(L) b) supposing 0 < ||L||

Lemma: round-robin-list-index
[T:Type]. ∀[eq:EqDecider(T)]. ∀[x:T]. ∀[L:T List].  (round-robin(L) outl(list-index(eq;L;x))) x ∈ supposing (x ∈ L)

Definition: ndlist
ndlist(T) ==  {L:T List| no_repeats(T;L)} 

Lemma: ndlist_wf
[T:Type]. (ndlist(T) ∈ Type)

Lemma: cons-ndlist
[T:Type]. ∀[L:ndlist(T)]. ∀[x:T].  [x L] ∈ ndlist(T) supposing ¬(x ∈ L)

Lemma: nil-ndlist
[T:Type]. ([] ∈ ndlist(T))

Definition: nd-append
L1@L2 ==  remove-repeats(eq;L1 L2)

Definition: vec
vec(T;n) ==  {L:T List| ||L|| n ∈ ℤ

Lemma: vec_wf
[T:Type]. ∀[n:ℕ].  (vec(T;n) ∈ Type)

Definition: vnil
vnil() ==  []

Lemma: vnil_wf
[T:Type]. (vnil() ∈ vec(T;0))

Lemma: l_member-first
[A:Type]. ∀d:A List. ∀x:A. ∀eq:EqDecider(A).  ((x ∈ d)  (∃i:ℕ||d||. ((∀j:ℕi. (d[j] x ∈ A))) ∧ (d[i] x ∈ A))))

Definition: retract
retract(T;f) ==  (∀x:T. ((f x) x ∈ T)) ∧ (∀x:Base. ((f x)↓  (x ∈ T)))

Lemma: retract_wf
[T:Type]. ∀[f:Base].  retract(T;f) ∈ ℙ supposing T ⊆Base

Definition: retract-compose
retract-compose(h;f) ==  λx.eval in x

Lemma: retract-compose_wf
[T,A:Type]. ∀[f:T ⟶ A]. ∀[h:Base].
  (retract-compose(h;f) ∈ {g:T ⟶ A| f ∈ (T ⟶ A)} supposing (((T ⊆Base) ∧ (A ⊆Base) ∧ retract(T;h)) and value\000C-type(T))

Lemma: cardinality-le-list-set
[T:Type]. ((∀x,y:T.  Dec(x y ∈ T))  (∀L:T List. |{x:T| (x ∈ L)} | ≤ ||L||))

Lemma: finite-type-list
[T:Type]. ((∀x,y:T.  Dec(x y ∈ T))  (∀L:T List. finite-type({x:T| (x ∈ L)} )))

Lemma: decidable__all-list
[T:Type]
  ((∀x,y:T.  Dec(x y ∈ T))
   (∀L:T List. ∀[P:{x:T| (x ∈ L)}  ⟶ ℙ]. ((∀x:{x:T| (x ∈ L)} Dec(P[x]))  Dec(∀x:{x:T| (x ∈ L)} P[x]))))

Definition: l_index
index(L;x) ==  mu(λi.(dT L[i]))

Lemma: l_index_wf
[T:Type]. ∀[dT:EqDecider(T)]. ∀[L:T List]. ∀[x:T].  index(L;x) ∈ ℕ||L|| supposing (x ∈ L)

Lemma: l_index_hd
[T:Type]. ∀[dT:EqDecider(T)]. ∀[L:T List].  index(L;hd(L)) supposing ¬↑null(L)

Lemma: select_l_index
[T:Type]. ∀[dT:EqDecider(T)]. ∀[L:T List]. ∀[x:T].  L[index(L;x)] x ∈ supposing (x ∈ L)

Lemma: l_before_l_index
[T:Type]
  ∀dT:EqDecider(T). ∀L:T List. ∀x,y:T.  ((x ∈ L)  (y ∈ L)  before y ∈ supposing index(L;x) < index(L;y))

Lemma: l_before_l_index_le
[T:Type]
  ∀dT:EqDecider(T). ∀L:T List. ∀x,y:T.
    ((x ∈ L)  (y ∈ L)  before y ∈ L ∨ (x y ∈ T) supposing index(L;x) ≤ index(L;y))

Lemma: no_repeats_mu_index
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[i:ℕ||L||].  mu(λi@0.(eq L[i] L[i@0])) i ∈ ℤ supposing no_repeats(T;L)

Lemma: no_repeats_l_index
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List]. ∀[i:ℕ||L||].  index(L;L[i]) supposing no_repeats(T;L)

Lemma: no_repeats_l_index-inj
[T:Type]. ∀[eq:EqDecider(T)]. ∀[L:T List].  Inj({x:T| (x ∈ L)} ;ℕ||L||;λx.index(L;x)) supposing no_repeats(T;L)

Definition: l_intersection
(L1 ⋂ L2) ==  filter(λx.x ∈b L2;L1)

Lemma: l_intersection_wf
[A:Type]. ∀[eq:EqDecider(A)]. ∀[L1,L2:A List].  ((L1 ⋂ L2) ∈ List)

Lemma: member-intersection
[A:Type]. ∀eq:EqDecider(A). ∀L1,L2:A List. ∀x:A.  ((x ∈ (L1 ⋂ L2)) ⇐⇒ (x ∈ L1) ∧ (x ∈ L2))

Lemma: no_repeats-intersection
[A:Type]. ∀eq:EqDecider(A). ∀L1,L2:A List.  (no_repeats(A;L1)  no_repeats(A;(L1 ⋂ L2)))

Lemma: l_intersection_nil
[A:Type]. ∀eq:EqDecider(A). ∀L:A List.  ((L ⋂ []) [] ∈ (A List))

Lemma: l_disjoint_intersection
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b,c:T List].  l_disjoint(T;(b ⋂ c);a) supposing l_disjoint(T;b;a) ∨ l_disjoint(T;c;a)

Lemma: l_disjoint_intersection2
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b,c:T List].  l_disjoint(T;a;(b ⋂ c)) supposing l_disjoint(T;a;b) ∨ l_disjoint(T;a;c)

Lemma: disjoint-iff-null-intersection
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b:T List].  uiff(l_disjoint(T;a;b);(a ⋂ b) [] ∈ (T List))

Lemma: l_disjoint_intersection_implies
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b:T List].  l_disjoint(T;a;b) supposing l_disjoint(T;a;(a ⋂ b))

Lemma: l_disjoint_intersection_implies2
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b:T List].  l_disjoint(T;a;b) supposing l_disjoint(T;b;(a ⋂ b))

Lemma: l_intersection-size
[T:Type]. ∀[eq:EqDecider(T)]. ∀[a,b,c:T List].
  (no_repeats(T;a)  no_repeats(T;b)  a ⊆  b ⊆  ((||a|| ||b||) ≤ (||c|| ||(a ⋂ b)||)))

Lemma: atom2-deq-aux
[a,b:Atom2].  uiff(a b ∈ Atom2;↑=a2 b)

Definition: atom2-deq
Atom2Deq ==  λa,b. =a2 b

Lemma: atom2-deq_wf
Atom2Deq ∈ EqDecider(Atom2)

Definition: name
Name ==  Atom List

Lemma: name_wf
Name ∈ Type

Lemma: name-valueall-type
valueall-type(Name)

Definition: name-deq
NameDeq ==  list-deq(AtomDeq)

Lemma: name-deq_wf
NameDeq ∈ EqDecider(Name)

Lemma: sq-decider-name-deq
sq-decider(NameDeq)

Definition: name_eq
name_eq(x;y) ==  NameDeq y

Lemma: name_eq_wf
[x,y:Name].  (name_eq(x;y) ∈ 𝔹)

Lemma: assert-name_eq
[x,y:Name].  uiff(↑name_eq(x;y);x y ∈ Name)

Lemma: assert-name-deq
[x,y:Name].  uiff(↑(NameDeq y);x y ∈ Name)

Lemma: name_eq-is-inl
[x,y,z:Base].  supposing name_eq(x;y) inl z

Lemma: not-name_eq-implies-sq-bfalse
[hdr1,hdr2:Name].  name_eq(hdr1;hdr2) ff supposing ¬(hdr1 hdr2 ∈ Name)

Lemma: decidable__equal_name
x,y:Name.  Dec(x y ∈ Name)

Lemma: name_eq_symmetry
[x,y:Name].  (name_eq(x;y) name_eq(y;x))

Lemma: name_eq-normalize-name
[X,F,G:Top]. ∀[a,b:Name].
  (case name_eq(a;b) ∧b of inl(x) => F[x;a] inr(x) => G[x] case name_eq(a;b) ∧b X
   of inl(x) =>
   F[x;b]
   inr(x) =>
   G[x])

Lemma: name_eq_spread
[x,y,F:Top].  (name_eq(let a,b in F[a;b];y) let a,b in name_eq(F[a;b];y))

Lemma: name_eq-normalize-name2
[X,F,G:Top]. ∀[a,b:Name].  (if name_eq(a;b) ∧b then else fi  if name_eq(a;b) ∧b then else fi )

Lemma: name_eq-normalize
[F,G,a,b:Top].  (if name_eq(a;b) then else fi  if name_eq(a;b) then else fi )

Lemma: name_eq-normalize2
[F,G,X,a,b:Top].
  (case name_eq(a;b) ∧b of inl(x) => inr(y) => case name_eq(a;b) ∧b of inl(x) => inr(y) => G)

Lemma: name_eq-normalize3
[F,G,X,a,b:Top].
  (case name_eq(a;b) ∧b of inl(x) => F[a] inr(y) => case name_eq(a;b) ∧b of inl(x) => F[b] inr(y) => G)

Lemma: name_eq-normalize4
[F,G,a,b:Top].  (case name_eq(a;b) of inl(x) => inr(y) => case name_eq(a;b) of inl(x) => inr(y) => G)

Lemma: name_eq-normalize-left
[F,G,a,b:Top].  (case name_eq(a;b) of inl(x) => inr(y) => case name_eq(a;b) of inl(x) => inr(y) => G)

Lemma: equal-by-name-cases
a,x,y:Name.
  ∀T:Type. ∀z:T. ∀P,Q:ℙ. ∀t1:⋂p:P. T. ∀t2:⋂q:Q. T.
    (((a x ∈ Name) ∧ P ∧ (z t1 ∈ T)) ∨ ((a y ∈ Name) ∧ Q ∧ (z t2 ∈ T))
    ⇐⇒ (((a x ∈ Name) ∧ P) ∨ ((a y ∈ Name) ∧ Q)) ∧ (z if name_eq(a;x) then t1 else t2 fi  ∈ T)) 
  supposing ¬(x y ∈ Name)

Definition: name-subst
name-subst(s;x) ==  case apply-alist(NameDeq;s;x) of inl(z) => inr(z) => x

Lemma: name-subst_wf
[s:(Name × Name) List]. ∀[x:Name].  (name-subst(s;x) ∈ Name)

Definition: nat-to-str
nat-to-str(n) ==
  fix((λnat-to-str,n. if (n =z 0) then [0]
                     if (n =z 1) then [1]
                     if (n =z 2) then [2]
                     if (n =z 3) then [3]
                     if (n =z 4) then [4]
                     if (n =z 5) then [5]
                     if (n =z 6) then [6]
                     if (n =z 7) then [7]
                     if (n =z 8) then [8]
                     if (n =z 9) then [9]
                     else (nat-to-str (n ÷ 10)) (nat-to-str (n rem 10))
                     fi )) 
  n

Lemma: nat-to-str_wf
[n:ℕ]. (nat-to-str(n) ∈ Atom List)

Lemma: member-nat-to-str
n:ℕ. ∀s:Atom.  ((s ∈ nat-to-str(n))  (s ∈ ``0 9``))

Definition: str1-to-nat
str1-to-nat(a) ==
  if =a "1" then 1
  if =a "2" then 2
  if =a "3" then 3
  if =a "4" then 4
  if =a "5" then 5
  if =a "6" then 6
  if =a "7" then 7
  if =a "8" then 8
  if =a "9" then 9
  else 0
  fi 

Lemma: str1-to-nat_wf
[a:Atom]. (str1-to-nat(a) ∈ ℕ)

Definition: str-to-nat-plus
str-to-nat-plus(s;n) ==  rec-case(s) of [] => λx.x fst::rest => rec.λx.(rec (str1-to-nat(fst) (10 x))) n

Lemma: str-to-nat-plus_wf
[s:Atom List]. ∀[n:ℕ].  (str-to-nat-plus(s;n) ∈ ℕ)

Definition: str-to-nat
str-to-nat(s) ==  str-to-nat-plus(s;0)

Lemma: str-to-nat_wf
[s:Atom List]. (str-to-nat(s) ∈ ℕ)

Lemma: str-to-nat-plus-property
[s:Atom List]. ∀[n:ℕ].  (str-to-nat-plus(s;n) (str-to-nat(s) (n 10^||s||)) ∈ ℤ)

Lemma: str-to-nat-to-str
[n:ℕ]. (str-to-nat(nat-to-str(n)) n ∈ ℤ)

Definition: mu-ge-print
mu-ge-print(f;n) ==
  fix((λmu-ge,n. if then else eval in eval evalall(nat-to-str(m)) in   print_line(s; mu-ge m) fi )) \000Cn

Definition: find-xover-print
find-xover-print(f;m;n;step) ==
  fix((λfind-xover,m,n,step. eval evalall(nat-to-str(n)) in
                             print_line(s;
                                        if n
                                        then <n, m>
                                        else eval step' step in
                                             eval step in
                                               find-xover step'
                                        fi ))) 
  
  
  step

Definition: nat-to-incomparable
nat-to-incomparable(n) ==  nat-to-str(n) [/]

Lemma: nat-to-incomparable_wf
[n:ℕ]. (nat-to-incomparable(n) ∈ Name)

Lemma: nat-to-incomparable-property
[n,m:ℕ].  ¬nat-to-incomparable(n) ≤ nat-to-incomparable(m) supposing ¬(n m ∈ ℤ)

Definition: maybe-new
maybe-new(s;avoid) ==  if s ∈b avoid then let mu(λn.(¬bnat-to-str(n) ∈b avoid)) in nat-to-str(n) else fi 

Lemma: maybe-new_wf
[s:Name]. ∀[avoid:Name List].  (maybe-new(s;avoid) ∈ {s':Name| ¬(s' ∈ avoid)} )

Definition: Id
Id ==  Atom2

Lemma: Id_wf
Id ∈ Type

Lemma: Id_sq
SQType(Id)

Lemma: Id-valueall-type
valueall-type(Id)

Lemma: Id-has-valueall
[x:Id]. has-valueall(x)

Lemma: Id-has-value
[x:Id]. (x)↓

Lemma: free-from-atom-Id
[i:Id]. ∀[a:Atom1].  a#i:Id

Lemma: free-from-atom-Id-rw
[i:Id]. ∀[a:Atom1].  uiff(a#i:Id;True)

Definition: mkid
"$x" ==  '$x'2

Lemma: mkid-wf-test
"xxx" ∈ Id

Definition: id-deq
IdDeq ==  Atom2Deq

Lemma: id-deq_wf
IdDeq ∈ EqDecider(Id)

Definition: eq_id
==  IdDeq b

Lemma: eq_id_wf
[a,b:Id].  (a b ∈ 𝔹)

Lemma: eq_id_self
[a:Id]. (a tt)

Lemma: assert-eq-id
[a,b:Id].  uiff(↑b;a b ∈ Id)

Lemma: decidable__equal_Id
a,b:Id.  Dec(a b ∈ Id)

Lemma: eq_id_test
("x" "x" tt) ∧ ("x" "y" ff)

Lemma: apply-Id-alist-function
[x:Id]. ∀[F:Top]. ∀[L:Id List].  apply-alist(IdDeq;map(λx.<x, F[x]>;L);x) inl F[x] supposing (x ∈ L)

Definition: id-graph
Graph(S) ==  {i:Id| (i ∈ S)}  ⟶ ({i:Id| (i ∈ S)}  List)

Lemma: id-graph_wf
[S:Id List]. (Graph(S) ∈ Type)

Definition: id-graph-edge
(i⟶j)∈==  (j ∈ i)

Lemma: id-graph-edge_wf
[S:Id List]. ∀[G:Graph(S)]. ∀[i:{i:Id| (i ∈ S)} ]. ∀[j:Id].  ((i⟶j)∈G ∈ ℙ)

Lemma: id-graph-edge-implies-member
S:Id List. ∀G:Graph(S). ∀i:{i:Id| (i ∈ S)} . ∀j:Id.  ((i⟶j)∈ (j ∈ S))



Home Index