Require Export BasicDefinitions.
(** ** Formalisation of finite types using canonical structures and type classes *)
(** * Definition of finite Types *)
Class finTypeC  (type:eqType) : Type :=
FinTypeC {
enum: list type;
enum_ok: forall x: type, count enum x = 1
}.
Structure finType : Type :=
FinType
{
type:> eqType;
class: finTypeC type
}.
Arguments FinType type {class}.
Existing Instance class | 0.
(* This is a hack to work-around a problem with a class of hacks *)
Hint Extern 5 (finTypeC (EqType ?x)) => unfold x : typeclass_instances.
Canonical Structure finType_CS (X : Type) {p : eq_dec X} {class : finTypeC (EqType X)} : finType := FinType (EqType X).
(** Print the base type of [finType] in the Canonical Structure. *)
Arguments finType_CS (X) {_ _}.
Definition elem (F: finType) := @enum (type F) (class F).
Hint Unfold elem.
Hint Unfold class.
Hint Resolve elem_spec.
Hint Resolve enum_ok.
Hint Resolve allSub.

(** A properties that hold on every element of (elem X) hold for every element of the finType X *)
Theorem Equivalence_property_all (X: finType) (p: X -> Prop) :
(forall x, p x) <-> forall x, x el (elem X) -> p x.