End CanChoice.
Section SubChoice.
Variables (P : pred T) (sT : subType P).
Definition sub_choiceMixin := PcanChoiceMixin (@valK T P sT).
Definition sub_choiceClass := @Choice.Class sT (sub_eqMixin sT) sub_choiceMixin.
Canonical sub_choiceType := Choice.Pack sub_choiceClass.
End SubChoice.
Fact seq_choiceMixin : choiceMixin (seq T).
Canonical seq_choiceType := Eval hnf in ChoiceType (seq T) seq_choiceMixin.
End OneType.
Section TagChoice.
Variables (I : choiceType) (T_ : I -> choiceType).
Fact tagged_choiceMixin : choiceMixin {i : I & T_ i}.
Canonical tagged_choiceType :=
Eval hnf in ChoiceType {i : I & T_ i} tagged_choiceMixin.
End TagChoice.
Fact nat_choiceMixin : choiceMixin nat.
Canonical nat_choiceType := Eval hnf in ChoiceType nat nat_choiceMixin.
Definition bool_choiceMixin := CanChoiceMixin oddb.
Canonical bool_choiceType := Eval hnf in ChoiceType bool bool_choiceMixin.
Canonical bitseq_choiceType := Eval hnf in [choiceType of bitseq].
Definition unit_choiceMixin := CanChoiceMixin bool_of_unitK.
Canonical unit_choiceType := Eval hnf in ChoiceType unit unit_choiceMixin.
Definition option_choiceMixin T := CanChoiceMixin (@seq_of_optK T).
Canonical option_choiceType T :=
Eval hnf in ChoiceType (option T) (option_choiceMixin T).
Definition sig_choiceMixin T (P : pred T) : choiceMixin {x | P x} :=
sub_choiceMixin _.
Canonical sig_choiceType T (P : pred T) :=
Eval hnf in ChoiceType {x | P x} (sig_choiceMixin P).
Definition prod_choiceMixin T1 T2 := CanChoiceMixin (@tag_of_pairK T1 T2).
Canonical prod_choiceType T1 T2 :=
Eval hnf in ChoiceType (T1 * T2) (prod_choiceMixin T1 T2).
Definition sum_choiceMixin T1 T2 := PcanChoiceMixin (@opair_of_sumK T1 T2).
Canonical sum_choiceType T1 T2 :=
Eval hnf in ChoiceType (T1 + T2) (sum_choiceMixin T1 T2).
Definition tree_choiceMixin T := PcanChoiceMixin (GenTree.codeK T).
Canonical tree_choiceType T := ChoiceType (GenTree.tree T) (tree_choiceMixin T).
End ChoiceTheory.
Prenex Implicits xchoose choose.
Notation "[ 'choiceMixin' 'of' T 'by' <: ]" :=
(sub_choiceMixin _ : choiceMixin T)
(at level 0, format "[ 'choiceMixin'  'of'  T  'by'  <: ]") : form_scope.
Module Countable.
Record mixin_of (T : Type) : Type := Mixin {
pickle : T -> nat;
unpickle : nat -> option T;
pickleK : pcancel pickle unpickle
}.
Definition EqMixin T m := PcanEqMixin (@pickleK T m).
Definition ChoiceMixin T m := PcanChoiceMixin (@pickleK T m).
Section ClassDef.
Record class_of T := Class { base : Choice.class_of T; mixin : mixin_of T }.
Local Coercion base : class_of >-> Choice.class_of.
Structure type : Type := Pack {sort : Type; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
Variables (T : Type) (cT : type).
Definition class := let: Pack _ c as cT' := cT return class_of cT' in c.
Definition clone c of phant_id class c := @Pack T c.
Let xT := let: Pack T _ := cT in T.
Notation xclass := (class : class_of xT).
Definition pack m :=
fun bT b & phant_id (Choice.class bT) b => Pack (@Class T b m).
Definition eqType := @Equality.Pack cT xclass.
Definition choiceType := @Choice.Pack cT xclass.
End ClassDef.
Module Exports.
Coercion base : class_of >-> Choice.class_of.
Coercion mixin : class_of >-> mixin_of.
Coercion sort : type >-> Sortclass.
Coercion eqType : type >-> Equality.type.
Canonical eqType.
Coercion choiceType : type >-> Choice.type.
Canonical choiceType.
Notation countType := type.
Notation CountType T m := (@pack T m _ _ id).
Notation CountMixin := Mixin.
Notation CountChoiceMixin := ChoiceMixin.
Notation "[ 'countType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
(at level 0, format "[ 'countType'  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'countType' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'countType'  'of'  T ]") : form_scope.
End Exports.
End Countable.
Export Countable.Exports.
Definition unpickle T := Countable.unpickle (Countable.class T).
Definition pickle T := Countable.pickle (Countable.class T).
Arguments unpickle {T} n.
Arguments pickle {T} x.
Section CountableTheory.
Variable T : countType.

Lemma pickleK_inv : pcancel pickle pickle_inv.
Definition tag_countMixin := CountMixin pickle_taggedK.