(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
(******************************************************************************)
(*    The Finite interface describes Types with finitely many elements,       *)
(* supplying a duplicate-free sequence of all the elements. It is a subclass  *)
(* of Countable and thus of Choice and Equality. As with Countable, the       *)
(* interface explicitly includes these somewhat redundant superclasses to     *)
(* ensure that Canonical instance inference remains consistent. Finiteness    *)
(* could be stated more simply by bounding the range of the pickle function   *)
(* supplied by the Countable interface, but this would yield a useless        *)
(* computational interpretation due to the wasteful Peano integer encodings.  *)
(* Because the Countable interface is closely tied to the Finite interface    *)
(* and is not much used on its own, the Countable mixin is included inside    *)
(* the Finite mixin; this makes it much easier to derive Finite variants of   *)
(* interfaces, in this file for subFinType, and in the finalg library.        *)
(*    We define the following interfaces and structures:                      *)
(*         finType == the packed class type of the Finite interface.          *)
(*     FinType T m == the packed finType class for type T and Finite mixin m. *)
(*  Finite.axiom e <-> every x : T occurs exactly once in e : seq T.          *)
(*   FinMixin ax_e == the Finite mixin for T, encapsulating                   *)
(*                    ax_e : Finite.axiom e for some e : seq T.               *)
(*  UniqFinMixin uniq_e total_e == an alternative mixin constructor that uses *)
(*                    uniq_e : uniq e and total_e : e =i xpredT.              *)
(* PcanFinMixin fK == the Finite mixin for T, given f : T -> fT and g with fT *)
(*                    a finType and fK : pcancel f g.                         *)
(*  CanFinMixin fK == the Finite mixin for T, given f : T -> fT and g with fT *)
(*                    a finType and fK : cancel f g.                          *)
(*      subFinType == the join interface type for subType and finType.        *)
(*  [finType of T for fT] == clone for T of the finType fT.                   *)
(*  [finType of T] == clone for T of the finType inferred for T.              *)
(* [subFinType of T] == a subFinType structure for T, when T already has both *)
(*                    finType and subType structures.                         *)
(* [finMixin of T by <:] == a finType structure for T, when T has a subType   *)
(*                   structure over an existing finType.                      *)
(*   We define or propagate the finType structure appropriately for all basic *)
(* types : unit, bool, option, prod, sum, sig and sigT. We also define a      *)
(* generic type constructor for finite subtypes based on an explicit          *)
(* enumeration:                                                               *)
(*          seq_sub s == the subType of all x \in s, where s : seq T for some *)
(*                       eqType T; seq_sub s has a canonical finType instance *)
(*                       when T is a choiceType.                              *)
(*   adhoc_seq_sub_choiceType s, adhoc_seq_sub_finType s ==                   *)
(*                       non-canonical instances for seq_sub s, s : seq T,    *)
(*                       which can be used when T is not a choiceType.        *)
(* Bounded integers are supported by the following type and operations:       *)
(*    'I_n, ordinal n == the finite subType of integers i < n, whose          *)
(*                       enumeration is {0, ..., n.-1}. 'I_n coerces to nat,  *)
(*                       so all the integer arithmetic functions can be used  *)
(*                       with 'I_n.                                           *)
(*     Ordinal lt_i_n == the element of 'I_n with (nat) value i, given        *)
(*                       lt_i_n : i < n.                                      *)
(*       nat_of_ord i == the nat value of i : 'I_n (this function is a        *)
(*                       coercion so it is not usually displayed).            *)
(*         ord_enum n == the explicit increasing sequence of the i : 'I_n.    *)
(*  cast_ord eq_n_m i == the element j : 'I_m with the same value as i : 'I_n *)
(*                       given eq_n_m : n = m (indeed, i : nat and j : nat    *)
(*                       are convertible).                                    *)
(* widen_ord le_n_m i == a j : 'I_m with the same value as i : 'I_n, given    *)
(*                       le_n_m : n <= m.                                     *)
(*          rev_ord i == the complement to n.-1 of i : 'I_n, such that        *)
(*                       i + rev_ord i = n.-1.                                *)
(*            inord k == the i : 'I_n.+1 with value k (n is inferred from the *)
(*                       context).                                            *)
(*          sub_ord k == the i : 'I_n.+1 with value n - k (n is inferred from *)
(*                       the context).                                        *)
(*               ord0 == the i : 'I_n.+1 with value 0 (n is inferred from the *)
(*                       context).                                            *)
(*            ord_max == the i : 'I_n.+1 with value n (n is inferred from the *)
(*                       context).                                            *)
(*           bump h k == k.+1 if k >= h, else k (this is a nat function).     *)
(*         unbump h k == k.-1 if k > h, else k (this is a nat function).      *)
(*           lift i j == the j' : 'I_n with value bump i j, where i : 'I_n    *)
(*                       and j : 'I_n.-1.                                     *)
(*         unlift i j == None if i = j, else Some j', where j' : 'I_n.-1 has  *)
(*                       value unbump i j, given i, j : 'I_n.                 *)
(*         lshift n j == the i : 'I_(m + n) with value j : 'I_m.              *)
(*         rshift m k == the i : 'I_(m + n) with value m + k, k : 'I_n.       *)
(*          unsplit u == either lshift n j or rshift m k, depending on        *)
(*                       whether if u : 'I_m + 'I_n is inl j or inr k.        *)
(*            split i == the u : 'I_m + 'I_n such that i = unsplit u; the     *)
(*                       type 'I_(m + n) of i determines the split.           *)
(* Finally, every type T with a finType structure supports the following      *)
(* operations:                                                                *)
(*           enum A == a duplicate-free list of all the x \in A, where A is a *)
(*                     collective predicate over T.                           *)
(*             #|A| == the cardinal of A, i.e., the number of x \in A.        *)
(*       enum_val i == the i'th item of enum A, where i : 'I_(#|A|).          *)
(*      enum_rank x == the i : 'I_(#|T|) such that enum_val i = x.            *)
(* enum_rank_in Ax0 x == some i : 'I_(#|A|) such that enum_val i = x if       *)
(*                     x \in A, given Ax0 : x0 \in A.                         *)
(*      A \subset B == all x \in A satisfy x \in B.                           *)
(*      A \proper B == all x \in A satisfy x \in B but not the converse.      *)
(* [disjoint A & B] == no x \in A satisfies x \in B.                          *)
(*        image f A == the sequence of f x for all x : T such that x \in A    *)
(*                     (where a is an applicative predicate), of length #|P|. *)
(*                     The codomain of F can be any type, but image f A can   *)
(*                     only be used as a collective predicate is it is an     *)
(*                     eqType.                                                *)
(*          codom f == a sequence spanning the codomain of f (:= image f T).  *)
(*  [seq F | x : T in A] := image (fun x : T => F) A.                         *)
(*       [seq F | x : T] := [seq F | x <- {: T}].                             *)
(*      [seq F | x in A], [seq F | x] == variants without casts.              *)
(*        iinv im_y == some x such that P x holds and f x = y, given          *)
(*                     im_y : y \in image f P.                                *)
(*     invF inj_f y == the x such that f x = y, for inj_j : injective f with  *)
(*                     f : T -> T.                                            *)
(*  dinjectiveb A f == the restriction of f : T -> R to A is injective        *)
(*                     (this is a bolean predicate, R must be an eqType).     *)
(*     injectiveb f == f : T -> R is injective (boolean predicate).           *)
(*         pred0b A == no x : T satisfies x \in A.                            *)
(*    [forall x, P] == P (in which x can appear) is true for all values of x; *)
(*                     x must range over a finType.                           *)
(*    [exists x, P] == P is true for some value of x.                         *)
(*      [forall (x | C), P] := [forall x, C ==> P].                           *)
(*       [forall x in A, P] := [forall (x | x \in A), P].                     *)
(*      [exists (x | C), P] := [exists x, C && P].                            *)
(*       [exists x in A, P] := [exists (x | x \in A), P].                     *)
(* and typed variants [forall x : T, P], [forall (x : T | C), P],             *)
(*   [exists x : T, P], [exists x : T in A, P], etc.                          *)
(* -> The outer brackets can be omitted when nesting finitary quantifiers,    *)
(*    e.g., [forall i in I, forall j in J, exists a, f i j == a].             *)
(*       'forall_pP == view for [forall x, p _], for pP : reflect .. (p _).   *)
(*       'exists_pP == view for [exists x, p _], for pP : reflect .. (p _).   *)
(*     [pick x | P] == Some x, for an x such that P holds, or None if there   *)
(*                     is no such x.                                          *)
(*     [pick x : T] == Some x with x : T, provided T is nonempty, else None.  *)
(*    [pick x in A] == Some x, with x \in A, or None if A is empty.           *)
(* [pick x in A | P] == Some x, with x \in A s.t. P holds, else None.         *)
(*   [pick x | P & Q] := [pick x | P & Q].                                    *)
(* [pick x in A | P & Q] := [pick x | P & Q].                                 *)
(* and (un)typed variants [pick x : T | P], [pick x : T in A], [pick x], etc. *)
(* [arg min_(i < i0 | P) M] == a value i : T minimizing M : nat, subject      *)
(*                   to the condition P (i may appear in P and M), and        *)
(*                   provided P holds for i0.                                 *)
(* [arg max_(i > i0 | P) M] == a value i maximizing M subject to P and        *)
(*                   provided P holds for i0.                                 *)
(* [arg min_(i < i0 in A) M] == an i \in A minimizing M if i0 \in A.          *)
(* [arg max_(i > i0 in A) M] == an i \in A maximizing M if i0 \in A.          *)
(* [arg min_(i < i0) M] == an i : T minimizing M, given i0 : T.               *)
(* [arg max_(i > i0) M] == an i : T maximizing M, given i0 : T.               *)
(*   These are special instances of                                           *)
(* [arg[ord]_(i < i0 | P) F] == a value i : I, minimizing F wrt ord : rel T   *)
(*                              such that for all j : T, ord (F i) (F j)      *)
(*                              subject to the condition P, and provided P i0 *)
(*                              where I : finType, T : eqType and F : I -> T  *)
(* [arg[ord]_(i < i0 in A) F] == an i \in A minimizing F wrt ord, if i0 \in A.*)
(* [arg[ord]_(i < i0) F] == an i : T minimizing F wrt ord, given i0 : T.      *)
(******************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Module Finite.
Section RawMixin.
Variable T : eqType.
Definition axiom e := forall x : T, count_mem x e = 1.

(* Specifications: *)
Lemma uniq_enumP e : uniq e -> e =i T -> axiom e.
Definition CountMixin := EnumMixin count_enumP.