(** * Finite types *)
(* [fin n : Type] is a type with [n] inhabitants. It is isomorphic to [Coq.Vector.Fin.t] from the standard library, but we found this formulation easier to reason about. *)
(* In this compiler, we use [fin n] as the type of "block labels" in [Asm] programs (program locations that can be jumped to). In an earlier version, labels could be any type, but this restriction makes [Asm] programs easier to introspect for defining optimizations (though the current development doesn't make use of it). *)
(* The instances at the end derive categorical operations for the subcategories of [Fun] and [ktree] on finite types (instead of arbitrary types). *)
(* begin hide *)
Arith
Lia.
ITree
ITreeFacts
Basics.Category
Basics.CategorySub.
(* end hide *)
(* Type with [n] inhabitants. *)
Definition fin (n : nat) : Type := { x : nat | x < n }.
(* Hide proof terms. *)
(* N.B.: [x < n] unfolds to [S x < n], which is why we don't make the first field more precise. *)
Notation fi' i := (exist (fun j : nat => _) i _).
Program Definition f0 {n} : fin (S n) := fi' 0.
Next Obligation. lia. Defined.

Lemma unique_fin : forall n (i j : fin n),
proj1_sig i = proj1_sig j -> i = j.