From Undecidability.Shared.Libs.PSL Require Export BasicDefinitions.
From Undecidability.Shared.Libs.PSL Require Import Bijection.
(* ** 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 : core.
Hint Unfold class : core.
Hint Resolve elem_spec : core.
Hint Resolve enum_ok : core.
Hint Resolve allSub : core.

(* 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.