(* * Codable Class **)
(* Class of minimally codable types *)
Class codable (sig: Type) (X: Type) := {
encode : X -> list sig;
}.
Arguments encode {sig} {X} {_}.
(* either the type or the alphabet must be know at head: *)
Hint Mode codable - ! : typeclass_instances.
Hint Mode codable ! - : typeclass_instances.
(* right side must be fully known, left side at head *)
Hint Mode Retract ! + : typeclass_instances.
(* (* Both sides must be known at head. *)
Hint Mode Retract ! - : typeclass_instances.
Hint Mode Retract - ! : typeclass_instances. *)
Hint Extern 4 (codable (FinType(EqType ?sigX)) ?X) => cbn : typeclass_instances.
(* We often use the above coercion to write [cX x] instead of [encode x], because [encode x] can be ambigious, see [Encode_map] *)
Coercion encode : codable >-> Funclass.
Definition size (sig X : Type) (cX : codable sig X) (x : X) := length (cX x).
Arguments size {sig X cX} x, {_ _} _ _ (*legacy with two arguments*).
(* Hint database for encoding compatibility lemmas. For example, size functions are usually parametrised over an encoding. It doesn't matter for the size, whether we apply [Encode_map] on this encoding. This kind of lemmas is registered in this HintDb. *)
Create HintDb encode_comp.
Ltac simpl_comp := autorewrite with encode_comp.
Instance Encode_unit : codable Empty_set unit :=
{|
encode x := nil
|}.

Lemma Encode_unit_hasSize (t:unit) :
size t = 0.