(**  A generic wrapper type  **)
Canonical wrap T x := @Wrap T x.
Prenex Implicits unwrap wrap Wrap.
(** fun_scope below is deprecated and should eventually be removed. Use function_scope instead.                    **)
Declare Scope fun_scope.
Delimit Scope fun_scope with FUN.
Open Scope fun_scope.
Open Scope function_scope.
(**  Notations for argument transpose  **)
Notation "f ^~ y" := (fun x => f x y) : function_scope.
Notation "@^~ x" := (fun f => f x) : function_scope.
(** Definitions and notation for explicit functions with simplification, i.e., which simpl and /= beta expand (this is complementary to nosimpl).  **)
#[universes(template)]
Variant simpl_fun (aT rT : Type) := SimplFun of aT -> rT.
Section SimplFun.
Variables aT rT : Type.
Definition fun_of_simpl (f : simpl_fun aT rT) := fun x => let: SimplFun lam := f in lam x.
End SimplFun.
Coercion fun_of_simpl : simpl_fun >-> Funclass.
Notation "[ 'fun' : T => E ]" := (SimplFun (fun _ : T => E)) : function_scope.
Notation "[ 'fun' x => E ]" := (SimplFun (fun x => E)) : function_scope.
Notation "[ 'fun' x y => E ]" := (fun x => [fun y => E]) : function_scope.
Notation "[ 'fun' x : T => E ]" := (SimplFun (fun x : T => E))
(only parsing) : function_scope.
Notation "[ 'fun' x y : T => E ]" := (fun x : T => [fun y : T => E])
(only parsing) : function_scope.
Notation "[ 'fun' ( x : T ) y => E ]" := (fun x : T => [fun y => E])
(only parsing) : function_scope.
Notation "[ 'fun' x ( y : T ) => E ]" := (fun x => [fun y : T => E])
(only parsing) : function_scope.
Notation "[ 'fun' ( x : T ) ( y : U ) => E ]" := (fun x : T => [fun y : U => E])
(only parsing) : function_scope.
(**  For delta functions in eqtype.v.  **)
Definition SimplFunDelta aT rT (f : aT -> aT -> rT) := [fun z => f z z].
(** Extensional equality, for unary and binary functions, including syntactic sugar.                                                                      **)
Section ExtensionalEquality.
Variables A B C : Type.
Definition eqfun (f g : B -> A) : Prop := forall x, f x = g x.
Definition eqrel (r s : C -> B -> A) : Prop := forall x y, r x y = s x y.

(* Specifications: *)
Lemma frefl f : eqfun f f. Proof. by []. Qed.
Lemma fsym f g : eqfun f g -> eqfun g f. Proof. by move=> eq_fg x. Qed.
Lemma ftrans f g h : eqfun f g -> eqfun g h -> eqfun f h.
Lemma eq_inj : injective f -> f =1 g -> injective g.
Lemma bij_can_eq f' f'' : cancel f f' -> cancel f f'' -> f' =1 f''.
End Bijections.