(* (c) Copyright 2006-2019 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
Set Warnings "-notation-incompatible-format".
Set Warnings "notation-incompatible-format".
(*****************************************************************************)
(* This file provides representations for finite sets over a choiceType K,   *)
(* finite maps with keys in a choiceType K and the values in an arbitrary    *)
(* type V, and total functions from K to V with finite support.              *)
(* The domain (resp. support) of a finite map (resp. fintely supported       *)
(* function) is a finite set, and so is the codomain (resp. image) when V    *)
(* is a choice type.                                                         *)
(*                                                                           *)
(*                {fset K} == finite sets of elements of K                   *)
(*           {fmap K -> V} == finitely supported maps from K to V.           *)
(* {fsfun K -> T for dflt} == finitely supported functions                   *)
(*                     with default value dflt : K -> V outside the support  *)
(*                                                                           *)
(********* finite sets *******************************************************)
(*                                                                           *)
(* In the remainder, A and B are of type {fset K}.                           *)
(*                                                                           *)
(* - {fset K} is provided with a canonical structure of predType, in order   *)
(*   to enable the notation "a \in A"                                        *)
(* - There is a coercion from {fset K} to Type in order to interpret any     *)
(*   finset A as the subType of elements a : K such that a \in A.            *)
(*   Because of this coercion, writing a : A makes sense.                    *)
(*                                                                           *)
(* The following notations are in the %fset scope                            *)
(*            fset0 == the empty finite set                                  *)
(*         [fset k] == the singleton finite set {k}                          *)
(*          A `&` B == the intersection of A and B                           *)
(*          A `|` B == the union of A and B                                  *)
(*           a |` B == the union of singleton a and B                        *)
(*          A `\` B == the complement of B in A                              *)
(*           A `\ b == A without b                                           *)
(*          A `*` B == the cartesian product of A and B                      *)
(* [disjoint A & B] := A `&` B == 0                                          *)
(*         A `<=` B == A is a subset of B                                    *)
(*          A `<` B == A is a proper subset of B                             *)
(*            #|`A| == cardinal of A                                         *)
(*    fincl AsubB a == turns a : A  into an element of B                     *)
(*                     using a proof AsubB of A \fsubset B                   *)
(*         fsub B A == turns A : {fset K} into a {set B}                     *)
(*           f @` A == the image set of the collective predicate A by f.     *)
(*      f @2`(A, B) == the image set of A x B by the binary function f.      *)
(*           [` aA] == an element a of A such that val [` aA] = a            *)
(*                     where aA is a proof of a \in A                        *)
(*                                                                           *)
(* In order to support the following notations, we introduce three canonical *)
(* structure that reflect the finiteness of a predicate, in the following    *)
(* notations, p (resp q) are such finite predicates, which are ultimately    *)
(* represented by elements A (resp B) from {fset K}.                         *)
(*                                                                           *)
(*    [fset x in p | P] == the set of all x of type K, such that             *)
(*                         x \in p and P x where P is a predicate on K       *)
(*  [fset x in p | P & Q] := [set x in p | P && Q].                          *)
(*                                                                           *)
(* [fset E | x in p] == the set of all the values of the expression E, for x *)
(*                     drawn from the collective finite predicate p.         *)
(* [fset E | x in p & P] == the set of values of E for x drawn from p, such  *)
(*                     that P is true.                                       *)
(* [fset E | x in p, y in q] == the set of values of E for x drawn from p and*)
(*                     and y drawn from q; q may depend on x.                *)
(* [fset E | x in p, y in q & P] == the set of values of E for x drawn from  *)
(*                    p and y drawn from q; such that P is true.             *)
(* [fsetval x in p] == the set of (val x) for x in the finite predicate p    *)
(* [fsetval x in p | P ] == the set of (val x) for x in p, such that P       *)
(* [fsetval x in p | P & Q] := [fsetval x in p | P && Q]                     *)
(*                                                                           *)
(* For each notation above, there is an additional one with ':' instead of   *)
(* 'in' which is used to range over the finite type A instead of the finite  *)
(* set A, and the optional predicate is over A instead of K                  *)
(* For example:                                                              *)
(*    [fset x : A | P] := [fset x in {: A} | P]                              *)
(*                     == the set of all x of type A, such that P x          *)
(* [fset E | x : A] == the set of all the values of the expression E, for x  *)
(*                     drawn from the finite type A                          *)
(*                                                                           *)
(* For each [fset ...] or [fsetval ...] notation, there is a keyed variant   *)
(* written [fset[key] ...] or [fsetval[key] ...] for locking                 *)
(*                                                                           *)
(******* finite maps *********************************************************)
(*                                                                           *)
(* Finite maps are finite functions (from finfun) where the domain is        *)
(* obtained by the coercion of a {fset A} to the finType of its elements     *)
(* Operations on finmap:                                                     *)
(* The following notations are in the %fmap scope                            *)
(*                                                                           *)
(*           f.[? k] == returns Some v if k maps to v, otherwise None        *)
(*             f.[p] == returns v if p has type k \in f, and k maps to v     *)
(*        f.[k <- v] == f extended with the mapping k -> v                   *)
(*            domf f == finite set (of type {fset K}) of keys of f           *)
(*          codomf f == finite set (of type {fset V}) of values of f         *)
(*           k \in f == k is a key of f                                      *)
(*                   := k \in domf f                                         *)
(*            [fmap] == the empty finite map                                 *)
(* [fmap x : S => E] == the finmap defined by E on the support S             *)
(*           f.[& A] == f restricted to A (intersected with domf f)          *)
(*           f.[\ A] := f.[& domf `\` A]                                     *)
(*                   == f where all the keys in A have been removed          *)
(*           f.[~ k] := f.[\ [fset k]]                                       *)
(*             f + g == concatenation of f and g,                            *)
(*                      the keys of g override the keys of f                 *)
(*                                                                           *)
(******* finitely supported functions ****************************************)
(*                                                                           *)
(* Operation on function with finite support, i.e. finmap with default value *)
(* for elements outside of the support. Contrarly to finmap, these are total *)
(* function, so we provide a coercion to Funclass                            *)
(*                                                                           *)
(* {fsfun K -> T for dflt_fun} == finitely supported functions with default  *)
(*                                value dflt : K -> V outside the support    *)
(* {fsfun K -> T of x => dflt} := {fsfun K -> T for fun x => dflt}           *)
(*    {fsfun K -> T with dflt} := {fsfun K -> T for fun=> dflt}              *)
(*              {fsfun K -> K} := {fsfun K -> T for fun x => x}              *)
(*                                                                           *)
(*         [fsfun for dflt_fun] == the default fsfun                         *)
(*         [fsfun of x => dflt] == the default fsfun                         *)
(*    [fsfun x : A => F | dflt] == the fsfun which takes value F on type A   *)
(*                                 x has type A : {fset T}                   *)
(*   [fsfun x in A => F | dflt] == the fsfun which takes value F on set A    *)
(*                                 x has type T, and x in A : {fset T}       *)
(* we also provide untyped variants and variants where default is ommitted   *)
(* e.g.  [fsfun x : A => F] [fsfun x => F | default] [fsfun]...              *)
(* and many variants to give the possibility to insert a key : unit          *)
(* to prevent conversion from diverging, e.g.                                *)
(* [fsfun[key] x : A => F | default] and [fsfun[key] x in A => F | default]  *)
(*                ...                                                        *)
(*     (f \o g)%fsfun == composition of fsfun                                *)
(*     fsinjectiveb f == boolean predicate of injectivity of f               *)
(*****************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Reserved Notation "A `=` B" (at level 70, no associativity).
Reserved Notation "A `<>` B" (at level 70, no associativity).
Reserved Notation "A `==` B" (at level 70, no associativity).
Reserved Notation "A `!=` B" (at level 70, no associativity).
Reserved Notation "A `=P` B" (at level 70, no associativity).
Reserved Notation "f @`[ key ] A" (at level 24, key at level 0).
Reserved Notation "f @2`[ key ] ( A , B )"
(at level 24, format "f  @2`[ key ]  ( A ,  B )").
Reserved Notation "f @` A" (at level 24).
Reserved Notation "f @2` ( A , B )" (at level 24, format "f  @2`  ( A ,  B )").
(* unary *)
Reserved Notation "[ 'fset' E | x : T 'in' A ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset' E | x 'in' A ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset' E | x : A ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset'  x  :  T  'in'  A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset'  x  :  T  'in'  A  |  P ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fset' x 'in' A | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset' x 'in' A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset' x : T | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset' x : T | P & Q ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset'  x  :  T  'in' A  |  P  &  Q ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fset' x 'in' A | P & Q ]" (at level 0, x at level 99).
(* binary *)
Reserved Notation "[ 'fset' E | x : T 'in' A , y : T' 'in' B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99).
Reserved Notation "[ 'fset' E | x 'in' A , y 'in' B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99).
(* keyed parse only *)
Reserved Notation "[ 'fset[' key ] E | x : T 'in' A ]"
(at level 0, E, x at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A ]"
(at level 0, E, x at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A & P ]"
(at level 0, E, x at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A & P ]"
(at level 0, E, x at level 99).
Reserved Notation "[ 'fset[' key ] E | x : T 'in' A , y : T' 'in' B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A , y 'in' B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A , y : B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A , y 'in' B ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A , y : B ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A , y 'in' B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A , y 'in' B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x 'in' A , y : B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ] E | x : A , y : B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset[' key ]  x  :  T  'in'  A ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ]  x  :  T  'in'  A  |  P ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ] x 'in' A | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ] x 'in' A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ] x : T | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ] x : T | P & Q ]" (at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ]  x  :  T  'in' A  |  P  &  Q ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fset[' key ] x 'in' A | P & Q ]"
(at level 0, x at level 99).
(* printing only *)
Reserved Notation "[ 'f' 'set' E | x 'in' A ]"
(at level 0, E, x at level 99,
format "[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A ]"
(at level 0, E, x at level 99,
format "[ '[hv' 'f' 'set'  E '/ '  |  x  :  A ] ']'").
Reserved Notation "[ 'f' 'set' x 'in' A | P ]"
(at level 0, x at level 99, format "[ 'f' 'set'  x  'in'  A  |  P ]").
Reserved Notation "[ 'f' 'set' x 'in' A ]"
(at level 0, x at level 99, format "[ 'f' 'set'  x  'in'  A ]").
Reserved Notation "[ 'f' 'set' x : T | P ]"
(at level 0, x at level 99, format "[ 'f' 'set'  x  :  T  |  P ]").
Reserved Notation "[ 'f' 'set' x : T | P & Q ]"
(at level 0, x at level 99, format "[ 'f' 'set'  x  :  T  |  P  &  Q ]").
Reserved Notation "[ 'f' 'set' x 'in' A | P & Q ]"
(at level 0, x at level 99, format "[ 'f' 'set'  x  'in'  A  |  P  &  Q ]").
(* binary printing only *)
Reserved Notation "[ 'f' 'set' E | x 'in' A , y 'in' B ]"
(at level 0, E, x at level 99, A at level 200, y at level 99,
format "[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A , '/' y  'in'  B ] ']'").
Reserved Notation "{fset K }" (at level 0, format "{fset  K }").
Reserved Notation "[ 'fset' a ]"
(at level 0, a at level 99, format "[ 'fset'  a ]").
Reserved Notation "[ 'fset' a : T ]"
(at level 0, a at level 99, format "[ 'fset'  a   :  T ]").
Reserved Notation "A `&` B" (at level 48, left associativity).
Reserved Notation "A `*` B" (at level 46, left associativity).
Reserved Notation "A `+` B" (at level 54, left associativity).
Reserved Notation "A +` B"  (at level 54, left associativity).
Reserved Notation "A `|` B" (at level 52, left associativity).
Reserved Notation "a |` A"  (at level 52, left associativity).
Reserved Notation "A `\` B" (at level 50, left associativity).
Reserved Notation "A `\ b"  (at level 50, left associativity).
Reserved Notation "A `<=` B" (at level 70, no associativity).
Reserved Notation "A `<` B" (at level 70, no associativity).
(* This is left-associative due to historical limitations of the .. Notation. *)
Reserved Notation "[ 'fset' a1 ; a2 ; .. ; an ]"
(at level 0, a1 at level 99, format "[ 'fset'  a1 ;  a2 ;  .. ;  an ]").
Reserved Notation "[ 'disjoint' A & B ]".
(* Comprehensions *)
Reserved Notation "[ 'fset' E | x 'in' A & P ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset' E | x : A & P ]" (at level 0, E, x at level 99).
Reserved Notation "[ 'fset' E | x : A , y 'in' B ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x 'in' A , y : B ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x : A , y : B ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x 'in' A , y 'in' B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x : A , y 'in' B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x 'in' A , y : B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fset' E | x : A , y : B & P ]"
(at level 0, E, x, y at level 99).
Reserved Notation "[ 'fsetval' x 'in' A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval' x 'in' A | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval' x 'in' A | P & Q ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval' x : A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval' x : A | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval' x : A | P & Q ]" (at level 0, x at level 99).
(* keyed parse only *)
Reserved Notation "[ 'fsetval[' key ] x 'in' A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval[' key ] x 'in' A | P ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fsetval[' key ] x 'in' A | P & Q ]"
(at level 0, x at level 99).
Reserved Notation "[ 'fsetval[' key ] x : A ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval[' key ] x : A | P ]" (at level 0, x at level 99).
Reserved Notation "[ 'fsetval[' key ] x : A | P & Q ]"
(at level 0, x at level 99).
(* Print-only variants to work around the Coq pretty-printer K-term kink. *)
Reserved Notation "[ 'f' 'set' E | x 'in' A & P ]"
(at level 0, E, x at level 99,
format "[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A '/ '  &  P ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A & P ]"
(at level 0, E, x at level 99,
format "[ '[hv' 'f' 'set'  E '/ '  |  x  :  A '/ '  &  P ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A , y 'in' B ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  :  A , '/   '  y  'in'  B ] ']'").
Reserved Notation "[ 'f' 'set' E | x 'in' A , y : B ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A , '/   '  y  :  B ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A , y : B ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  :  A , '/   '  y  :  B ] ']'").
Reserved Notation "[ 'f' 'set' E | x 'in' A , y 'in' B & P ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A , '/   '  y  'in'  B '/ '  &  P ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A , y 'in' B & P ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  :  A , '/   '  y  'in'  B  &  P ] ']'").
Reserved Notation "[ 'f' 'set' E | x 'in' A , y : B & P ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  'in'  A , '/   '  y  :  B  &  P ] ']'").
Reserved Notation "[ 'f' 'set' E | x : A , y : B & P ]"
(at level 0, E, x, y at level 99, format
"[ '[hv' 'f' 'set'  E '/ '  |  x  :  A , '/   '  y  :  B  &  P ] ']'").
Reserved Notation "[ 'f' 'setval' x 'in' A ]"
(at level 0, x at level 99, format "[ 'f' 'setval'  x  'in'  A ]").
Reserved Notation "[ 'f' 'setval' x 'in' A | P ]"
(at level 0, x at level 99, format "[ 'f' 'setval'  x  'in'  A  |  P ]").
Reserved Notation "[ 'f' 'setval' x 'in' A | P & Q ]"
(at level 0, x at level 99,
format "[ 'f' 'setval'  x  'in'  A  |  P  &  Q ]").
Reserved Notation "[ 'f' 'setval' x : A ]"
(at level 0, x at level 99, format "[ 'f' 'setval'  x  :  A ]").
Reserved Notation "[ 'f' 'setval' x : A | P ]"
(at level 0, x at level 99, format "[ 'f' 'setval'  x  :  A  |  P ]").
Reserved Notation "[ 'f' 'setval' x : A | P & Q ]"
(at level 0, x at level 99, format "[ 'f' 'setval'  x  :  A  |  P  &  Q ]").
Reserved Notation "\bigcup_ ( i <- r | P ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \bigcup_ ( i  <-  r  |  P ) '/  '  F ']'").
Reserved Notation "\bigcup_ ( i <- r ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \bigcup_ ( i  <-  r ) '/  '  F ']'").
Reserved Notation "\bigcup_ ( i | P ) F"
(at level 41, F at level 41, i at level 50,
format "'[' \bigcup_ ( i  |  P ) '/  '  F ']'").
Reserved Notation "\bigcup_ ( i 'in' A | P ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \bigcup_ ( i  'in'  A  |  P ) '/  '  F ']'").
Reserved Notation "\bigcup_ ( i 'in' A ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \bigcup_ ( i  'in'  A ) '/  '  F ']'").
Reserved Notation "{fmap T }" (at level 0, format "{fmap  T }").
Reserved Notation "x .[ k <- v ]"
(at level 2, left associativity, format "x .[ k  <-  v ]").
Reserved Notation "x .[~ k ]" (at level 2, k at level 200, format "x .[~  k ]").
Reserved Notation "x .[& k ]" (at level 2, k at level 200, format "x .[&  k ]").
Reserved Notation "x .[\ k ]" (at level 2, k at level 200, format "x .[\  k ]").
Reserved Notation "x .[? k ]" (at level 2, k at level 200, format "x .[?  k ]").
Reserved Infix "`~`" (at level 52).
Reserved Notation "[ 'fset' k ]" (at level 0, k at level 99, format "[ 'fset'  k ]").
(* Copy of the ssrbool shim to ensure compatibility with MathComp v1.8.0. *)
Definition PredType : forall T pT, (pT -> pred T) -> predType T.
exact PredType || exact mkPredType.
Defined.
Arguments PredType [T pT] toP.
Local Notation predOfType T := (pred_of_simpl (@pred_of_argType T)).
Definition oextract (T : Type) (o : option T) : o -> T :=
if o is Some t return o -> T then fun=> t else False_rect T \o notF.

Lemma oextractE (T : Type) (x : T) (xP : Some x) : oextract xP = x.