(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
(******************************************************************************)
(* This file implements a type for functions with a finite domain:            *)
(*    {ffun aT -> rT} where aT should have a finType structure.               *)
(* Any eqType, choiceType, countType and finType structures on rT extend to   *)
(* {ffun aT -> rT} as Leibnitz equality and extensional equalities coincide.  *)
(*     (T ^ n)%type is notation for {ffun 'I_n -> T}, which is isomorphic     *)
(*                     to n.-tuple T.                                         *)
(*  For f : {ffun aT -> rT}, we define                                        *)
(*              f x == the image of x under f (f coerces to a CiC function)   *)
(*         fgraph f == the graph of f, i.e., the #|aT|.-tuple rT of the       *)
(*                     values of f over enum aT.                              *)
(*       finfun lam == the f such that f =1 lam; this is the RECOMMENDED      *)
(*                     interface to build an element of {ffun aT -> rT}.      *)
(* [ffun x => expr] == finfun (fun x => expr)                                 *)
(*   [ffun => expr] == finfun (fun _ => expr)                                 *)
(*  f \in ffun_on R == the range of f is a subset of R                        *)
(*   f \in family F == f belongs to the family F (f x \in F x for all x)      *)
(*     y.-support f == the y-support of f, i.e., [pred x | f x != y].         *)
(*                     Thus, y.-support f \subset D means f has y-support D.  *)
(*                     We will put Notation support := 0.-support in ssralg.  *)
(* f \in pffun_on y D R == f is a y-partial function from D to R:             *)
(*                     f has y-support D and f x \in R for all x \in D.       *)
(*  f \in pfamily y D F == f belongs to the y-partial family from D to F:     *)
(*                     f has y-support D and f x \in F x for all x \in D.     *)
(******************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Section Def.
Variables (aT : finType) (rT : Type).
Inductive finfun_type : predArgType := Finfun of #|aT|.-tuple rT.
Definition finfun_of of phant (aT -> rT) := finfun_type.
Identity Coercion type_of_finfun : finfun_of >-> finfun_type.
Definition fgraph f := let: Finfun t := f in t.
Canonical finfun_subType := Eval hnf in [newType for fgraph].
End Def.
Notation "{ 'ffun' fT }" := (finfun_of (Phant fT))
(at level 0, format "{ 'ffun'  '[hv' fT ']' }") : type_scope.
Definition exp_finIndexType n := ordinal_finType n.
Notation "T ^ n" := (@finfun_of (exp_finIndexType n) T (Phant _)) : type_scope.
Local Notation fun_of_fin_def :=
(fun aT rT f x => tnth (@fgraph aT rT f) (enum_rank x)).
Local Notation finfun_def := (fun aT rT f => @Finfun aT rT (codom_tuple f)).
Module Type FunFinfunSig.
Parameter fun_of_fin : forall aT rT, finfun_type aT rT -> aT -> rT.
Parameter finfun : forall (aT : finType) rT, (aT -> rT) -> {ffun aT -> rT}.

Axiom fun_of_finE : fun_of_fin = fun_of_fin_def.