+notation < "𝐅" non associative with precedence 90
+ for @{'bigF}.
+interpretation "FinSet" 'bigF = (mk_FinSet ???).
+
+(* bool *)
+lemma bool_enum_unique: uniqueb ? [true;false] = true.
+// qed.
+
+lemma bool_enum_complete: ∀x:bool. memb ? x [true;false] = true.
+* // qed.
+
+definition FinBool ≝
+ mk_FinSet DeqBool [true;false] bool_enum_unique bool_enum_complete.
+
+unification hint 0 ≔ ;
+ X ≟ FinBool
+(* ---------------------------------------- *) ⊢
+ bool ≡ FinSetcarr X.
+
+(* nat segment *)
+
+lemma eqbnat_true : ∀n,m. eqb n m = true ↔ n = m.
+#n #m % [@eqb_true_to_eq | @eq_to_eqb_true]
+qed.
+
+definition DeqNat ≝ mk_DeqSet nat eqb eqbnat_true.
+
+lemma lt_to_le : ∀n,m. n < m → n ≤ m.
+/2/ qed-.
+
+let rec enumnaux n m ≝
+ match n return (λn.n ≤ m → list (Σx.x < m)) with
+ [ O ⇒ λh.[ ] | S p ⇒ λh:p < m.(mk_Sig ?? p h)::enumnaux p m (lt_to_le p m h)].
+
+definition enumn ≝ λn.enumnaux n n (le_n n).
+
+definition Nat_to ≝ λn. DeqSig DeqNat (λi.i<n).
+
+(* lemma prova : ∀n. carr (Nat_to n) = (Σx.x<n). // *)
+
+lemma memb_enumn: ∀m,n,i:DeqNat. ∀h:n ≤ m. ∀k: i < m. n ≤ i →
+ (¬ (memb (Nat_to m) (mk_Sig ?? i k) (enumnaux n m h))) = true.
+#m #n elim n -n // #n #Hind #i #ltm #k #ltni @sym_eq @noteq_to_eqnot @sym_not_eq
+% #H cases (orb_true_l … H)
+ [whd in ⊢ (??%?→?); #H1 @(absurd … ltni) @le_to_not_lt
+ >(eqb_true_to_eq … H1) @le_n
+ |<(notb_notb (memb …)) >Hind normalize /2 by lt_to_le, absurd/
+ ]
+qed.
+
+lemma enumn_unique_aux: ∀n,m. ∀h:n ≤ m. uniqueb (Nat_to m) (enumnaux n m h) = true.
+#n elim n -n // #n #Hind #m #h @true_to_andb_true // @memb_enumn //
+qed.
+
+lemma enumn_unique: ∀n.uniqueb (Nat_to n) (enumn n) = true.
+#n @enumn_unique_aux
+qed.
+
+(* definition ltb ≝ λn,m.leb (S n) m. *)
+lemma enumn_complete_aux: ∀n,m,i.∀h:n ≤m.∀k:i<m.i<n →
+ memb (Nat_to m) (mk_Sig ?? i k) (enumnaux n m h) = true.
+#n elim n -n
+ [normalize #n #i #_ #_ #Hfalse @False_ind /2/
+ |#n #Hind #m #i #h #k #lein whd in ⊢ (??%?);
+ cases (le_to_or_lt_eq … (le_S_S_to_le … lein))
+ [#ltin cut (eqb (Nat_to m) (mk_Sig ?? i k) (mk_Sig ?? n h) = false)
+ [normalize @not_eq_to_eqb_false @lt_to_not_eq @ltin]
+ #Hcut >Hcut @Hind //
+ |#eqin cut (eqb (Nat_to m) (mk_Sig ?? i k) (mk_Sig ?? n h) = true)
+ [normalize @eq_to_eqb_true //
+ |#Hcut >Hcut %
+ ]
+ ]
+qed.
+
+lemma enumn_complete: ∀n.∀i:Nat_to n. memb ? i (enumn n) = true.
+#n whd in ⊢ (%→?); * #i #ltin @enumn_complete_aux //
+qed.
+
+definition initN ≝ λn.
+ mk_FinSet (Nat_to n) (enumn n) (enumn_unique n) (enumn_complete n).
+
+example tipa: ∀n.∃x: initN (S n). pi1 … x = n.
+#n @ex_intro [whd @mk_Sig [@n | @le_n] | //] qed.
+
+(* option *)
+definition enum_option ≝ λA:DeqSet.λl.
+ None A::(map ?? (Some A) l).
+
+lemma enum_option_def : ∀A:FinSet.∀l.
+ enum_option A l = None A :: (map ?? (Some A) l).
+// qed.
+
+lemma enum_option_unique: ∀A:DeqSet.∀l.
+ uniqueb A l = true →
+ uniqueb ? (enum_option A l) = true.
+#A #l #uA @true_to_andb_true
+ [generalize in match uA; -uA #_ elim l [%]
+ #a #tl #Hind @sym_eq @noteq_to_eqnot % #H
+ cases (orb_true_l … (sym_eq … H))
+ [#H1 @(absurd (None A = Some A a)) [@(\P H1) | % #H2 destruct]
+ |-H #H >H in Hind; normalize /2/
+ ]
+ |@unique_map_inj // #a #a1 #H destruct %
+ ]
+qed.
+
+lemma enum_option_complete: ∀A:DeqSet.∀l.
+ (∀x:A. memb A x l = true) →
+ ∀x:DeqOption A. memb ? x (enum_option A l) = true.
+#A #l #Hl * // #a @memb_cons @memb_map @Hl
+qed.
+
+definition FinOption ≝ λA:FinSet.
+ mk_FinSet (DeqOption A)
+ (enum_option A (enum A))
+ (enum_option_unique … (enum_unique A))
+ (enum_option_complete … (enum_complete A)).
+
+unification hint 0 ≔ C;
+ T ≟ FinSetcarr C,
+ X ≟ FinOption C
+(* ---------------------------------------- *) ⊢
+ option T ≡ FinSetcarr X.
+
+(* sum *)