Section hfs.
Definition hfs : Set := sig (fun t => bt_norm t = t).
Definition bt_cls (t : bt) : hfs.
Fact hfs_repr_bt_cls t : hfs_repr (bt_cls t) ≈ t.
Fact bt_cls_equiv s t : bt_cls s = bt_cls t <-> s ≈ t.
Fact bt_cls_hfs_repr_iff t s : cls t = s <-> t ≈ repr s.
Definition hfs_eq_dec : forall (s t : hfs), { s = t } + { s <> t }.
Definition hfs_mem s t := bt_mem (repr s) (repr t).
Infix "∈" := hfs_mem.
Arguments hfs_mem s t /.
Fact btm_cls_repr t s : cls t ∈ s <-> bt_mem t (repr s).
Fact btm_repr_cls t s : t ∈ cls s <-> bt_mem (repr t) s.
Fact hfs_mem_btm s t : cls s ∈ cls t <-> bt_mem s t.
Fact hfs_mem_wf : well_founded hfs_mem.
Fact hfs_mem_dec : forall s t, { s ∈ t } + { ~ s ∈ t }.
Definition hfs_empty : hfs := exist _ bt_leaf eq_refl.
Notation "∅" := hfs_empty.
Fact hfs_empty_prop : forall x, ~ x ∈ ∅.
Fact hfs_empty_spec x : x ∈ ∅ <-> False.
Definition hfs_cons x t := cls ((repr x)⪧(repr t)).
Fact hfs_cons_spec y x t : y ∈ hfs_cons x t <-> y = x \/ y ∈ t.
Opaque hfs_empty hfs_cons hfs_mem.
(* This is the decidable comprehension *)
Fact hfs_select t (P : hfs -> Prop) :
(forall x, x ∈ t -> { P x } + { ~ P x })
-> { s | forall x, x ∈ s <-> x ∈ t /\ P x }.
Definition hfs_pow t := cls (bt_pow (repr t)).
Notation "x ⊆ y" := (forall u, u ∈ x -> u ∈ y).
Fact hfs_incl_refl r : r ⊆ r.
Fact hfs_pow_spec s x : x ∈ hfs_pow s <-> x ⊆ s.
Definition hfs_transitive t := forall u v, u ∈ v -> v ∈ t -> u ∈ t.
Fact bt_hfs_transitive t : hfs_transitive t <-> bt_transitive (repr t).
Definition hfs_tc t := cls (bt_tc (repr t)).
Fact hfs_tc_trans t : hfs_transitive (hfs_tc t).
Fact hfs_tc_incl t : t ⊆ hfs_tc t.
Fact hfs_pow_trans t : hfs_transitive t -> hfs_transitive (hfs_pow t).
Definition hfs_card n := cls (nat2bt n).
Fact hfs_card_transitive n : hfs_transitive (hfs_card n).
Definition hfs_pos n (p : pos n) := cls (pos2bt p).
Fact hfs_pos_card n x : x ∈ hfs_card n <-> exists p, x = @hfs_pos n p.
Fact hfs_card_empty n : ∅ ∈ hfs_card (S n).
Fact hfs_pos_prop n p : @hfs_pos n p ∈ hfs_card n.
Definition hfs_card_pos n x : x ∈ hfs_card n -> pos n.
Fact hfs_pos_inj n p q : @hfs_pos n p = hfs_pos q -> p = q.
Fact hfs_card_pos_pirr n x H1 H2 : @hfs_card_pos n x H1 = @hfs_card_pos n x H2.
(* For the non-empty finite type pos (S n), there is a computably surjective map from a transitive set l onto pos (S n)  The case of the empty model is rules out in our case because we always need to be able to interpret some variable in unscoped De Bruijn syntax *)

Theorem hfs_pos_n_transitive n :
{ l : hfs & { f : hfs -> pos (S n) &
{ g : pos (S n) -> hfs |
hfs_transitive l
/\ ∅ ∈ l
/\ (forall p, g p ∈ l)
/\ (forall x, x ∈ l -> exists p, x = g p)
/\ (forall p, f (g p) = p) } } }.