regexp.concrete.function: Functions


Overview

  • s ~> A t A s: Concrete representation for the function type universe.t s A.
  • constant a : The constant function
  • transpose u : Flips the argument order of a bi-variate function u : (s1 ~> s2 ~> A).

Concrete Functions as Vectors.

Since universe.t s is a finite type, the concrete functions can indeed be seen as vector. The following functions are defined in this context.
  • map f u : Apply f on all the results (analogous to map for vectors)
  • zipWith f u v : Apply f on corresponding values (analogous to map2 for vectors)
  • fold op u : For an A-operator op : A A A, folds up the vector of values.

Inductive t {A} : sort Type :=
| const : A t 𝟙
| concat {s1 s2} : t s1 t s2 t (s1 s2).

Arguments t : clear implicits.

Bind Scope concrete_scope with t.
Infix "++" := function.concat : concrete_scope.
Notation "s ~> A" := (t A s) (at level 99, right associativity) : concrete_scope.

Fixpoint constant {A} (x : A) {s} : s ~> A :=
  match s with
  | 𝟙const x
  | s1 s2constant x ++ constant x
  end.


Fixpoint map {A B : Type}(f : A B) {s} (fA : s ~> A) : s ~> B:=
  match fA with
  | const aconst (f a)
  | fA1 ++ fA2map f fA1 ++ map f fA2
  end%con.

Lemma map_compose {A B C : Type}(f : B C) (g : A B){s}
  : map (s:=s) f \o map g =1 map (f \o g).
  elim ⇒ [|s1 s2 u1 IH1 u2 IH2].
  - movea; rewrite //=.
  - by rewrite //= -IH1 -IH2 //=.
Qed.

Lemma map_eqfun {A B : Type}(f g : A B): f =1 g s (u : s ~> A), map f u = map g u.
  moveH s.
  elim ⇒ [|s1 s2 u1 IH1 u2 IH2 ].
  - movea; by rewrite //= H.
  - by rewrite //= IH1 IH2.
Qed.

Definition unconst {A}(f : 𝟙 ~> A) : A :=
  match f with
  | const aa
  end.

Definition unsum {A s1 s2}(v : s1 s2 ~> A) : (s1 ~> A) × (s2 ~> A) :=
  match v with
  | v1 ++ v2(v1 , v2)
  end.

Lemma unconst_const {A} : u : 𝟙 ~> A, const (unconst u) = u.
  moveu.
  dependent destruction u; rewrite //=.
Qed.

Lemma unsum_sum {A s1 s2} : u : (s1 s2) ~> A, u1 u2 , u1 ++ u2 = u.
  moveu.
  dependent destruction u; by u1; u2.
Qed.

Fixpoint zipWith {A B C}(f : A B C) {s} : (s ~> A) (s ~> B) s ~> C :=
  match s with
  | 𝟙fun a bconst (f (unconst a) (unconst b))
  | s1 s2fun v1 v2let (v11, v12) := unsum v1 in
                        let (v21, v22) := unsum v2 in
                        (zipWith f v11 v21) ++ (zipWith f v12 v22)
  end.

Definition zipWith3 {A B C D}(f : A B C D) {s} (u : s ~> A)(v : s ~> B) : (s ~> C) s ~> D :=
  zipWith (fun f xf x) (zipWith f u v).

Definition zipWith4 {A B C D E}(f : A B C D E) {s}
  (u : s ~> A)(v : s ~> B)(w : s ~> C) : (s ~> D) s ~> E :=
  zipWith (fun f xf x) (zipWith3 f u v w).


Fixpoint fold {A} (f : A A A) {s} (v : s ~> A) : A :=
  match v with
  | const xx
  | v1 ++ v2f (fold f v1) (fold f v2)
  end.

Section FoldMap.
  Context {A B}(conv : A B).
  Context (f : A A A)(g : B B B).
  Context (Hconv : a1 a2, conv (f a1 a2) = g (conv a1) (conv a2)).

  Lemma fold_map {s} : u : s ~> A, fold g (map conv u) = conv (fold f u).
    elim ⇒ [|s1 s2 u1 IH1 u2 IH2].
    - by rewrite //=.
    - by rewrite //= IH1 IH2 Hconv.
  Qed.

End FoldMap.

Fixpoint transpose {A r c} : (r ~> c ~> A) c ~> r ~> A :=
  match r as r0 return (r0 ~> c ~> A) (c ~> r0 ~> A) with
  | 𝟙map const \o unconst
  | r1 r2fun vlet (v1 , v2) := unsum v in
                    zipWith concat (transpose v1) (transpose v2)
  end.

Semantics

For a sort s and an arbitrary type A, the type s ~> A should be seen as the type of concrete representation of the function type s A. The denotational semantics is given by the mathcomp finitary function from finite type universe.denote s to the type A.
Fixpoint to {A s} (func : s ~> A) : s A :=
  match func with
  | const afun _a
  | func1 ++ func2fun xmatch x with
                            | inl x1to func1 x1
                            | inr x2to func2 x2
                            end
  end.

Definition denote {s A} (func : s ~> A) : {ffun universe.denote s A} := finfun (to func).


Fixpoint from {A}{s : sort}: (s A) (s ~> A) :=
  match s as s0 return (s0 A) s0 ~> A with
  | 𝟙fun funcconst (func tt)
  | s1 s2 ⇒ (fun funcfrom (func \o inl) ++ from (func \o inr))
  end.

Lemma denoteE {s A}(func : s ~> A) : x, denote func x = func x.
  movex; by rewrite ffunE.
Qed.

Lemma constantE {s A}(a : A) : x, constant (s:=s) a x = a.
  induction s.
  - rewrite //=.
  - movex; by case x.
Qed.

Lemma fromeq {A}{s : sort} (f g : s A) (Hfext : f =1 g) : from f = from g.
  induction s as [|s1 IH1 s2 IH2].
  - by rewrite //= Hfext.
  - rewrite //=.
    have HL : f \o inl =1 g \o inl by [movex; rewrite /comp Hfext].
    have HR : f \o inr =1 g \o inr by [movex; rewrite /comp Hfext].
    by rewrite (IH1 _ _ HL) (IH2 _ _ HR).
Qed.

Lemma to_from {A} {s : sort} (f : s A) : from f =1 f.
  movex.
  induction s as [| s1 IH1 s2 IH2];
    destruct x; by rewrite //= ?IH1 ?IH2.
Qed.

Lemma from_to {A s}(v : s ~> A) : from (to v) = v.
  induction v as[| s1 s2 v1 IH1 v2 IH2]; by rewrite //= IH1 IH2.
Qed.

Lemma extensionality {A s} (v1 v2 : A ~> s) (Hexteq : v1 =1 v2) : v1 = v2.
  rewrite -(from_to v1) -(from_to v2); by apply fromeq.
Qed.

Lemma to_plus_1 {A s1 s2}(v1 : s1 ~> A) (v2 : s2 ~> A) : x, v1 x = (v1 ++ v2) (inl x).
  movex; rewrite //=.
Qed.
Lemma to_plus_2 {A s1 s2}(v1 : s1 ~> A) (v2 : s2 ~> A) : x, v2 x = (v1 ++ v2) (inr x).
  movex; rewrite //=.
Qed.

Lemma to_map {A B s} (f : A B) (v : s ~> A) : x : s, map f v x = f (v x).
  movex.
  induction v.
  - by destruct x.
  - destruct x; rewrite //=.
Qed.

Definition proj1 {A s1 s2}(v : s1 s2 ~> A) : s1 ~> A :=
  match v with
  | v1 ++ _v1
  end%con.

Definition proj2 {A s1 s2}(v : s1 s2 ~> A) : s2 ~> A :=
  match v with
  | _ ++ v2v2
  end%con.

Notation "p '.1'" := (function.proj1 p) (format "p .1") : concrete_scope.
Notation "p '.2'" := (function.proj2 p) (format "p .2") : concrete_scope.

Lemma sum_proj {A s1 s2} : x : s1 s2 ~> A , (x.1 ++ x.2 = x).
  movex.
  dependent destruction x.
  rewrite //=.
Qed.

Lemma proj_sum_1 {A s1 s2} : (x : s1 ~> A) (y : s2 ~> A), ((x ++ y).1 = x).
  trivial.
Qed.

Lemma proj_sum_2 {A s1 s2} : (x : s1 ~> A) (y : s2 ~> A), ((x ++ y).2 = y).
  trivial.
Qed.

Lemma to_proj1 {A s1 s2} (v : s1 s2 ~> A) (x : s1) : (v.1 x = v (inl x)).
  by dependent destruction v; rewrite //=.
Qed.

Lemma to_proj2 {A s1 s2} (v : s1 s2 ~> A ) (x : s2) : (v.2 x = v (inr x)).
  by dependent destruction v; rewrite //=.
Qed.

Lemma zip_pointwise {A B C}(f : A B C) {s} (va : s ~> A )(vb : s ~> B) (x : s)
  : zipWith f va vb x = f (va x) (vb x).
  induction va; dependent destruction vb; destruct x; by [rewrite //=].
Qed.

Lemma zip_pointwise3 {A B C D}(f : A B C D) {s} (va : s ~> A )(vb : s ~> B) (vc : s ~> C) (x : s)
  : zipWith3 f va vb vc x = f (va x) (vb x) (vc x).
  by rewrite /zipWith3 ?zip_pointwise.
Qed.

Lemma zip_pointwise4 {A B C D E}(f : A B C D E) {s}
  (va : s ~> A )(vb : s ~> B) (vc : s ~> C) (vd : s ~> D) (x : s)
  : zipWith4 f va vb vc vd x = f (va x) (vb x) (vc x) (vd x).
  by rewrite /zipWith3 ?zip_pointwise.
Qed.

Section ZipWithMap.
  Context {A B C : Type}(f : A B C).

  Section Right.
    Context {Bp Cp : Type}.
    Context (fp : A Bp Cp).
    Context (convB : B Bp)(convC : C Cp).
    Context (Hconv : (a : A)(b : B), convC (f a b) = fp a (convB b)).
    Lemma zipWith_mapR {s}(u : s ~> A)(v : s ~> B) : map convC (zipWith f u v) = zipWith fp u (map convB v).
      apply extensionalityx; by rewrite to_map ?zip_pointwise to_map Hconv.
    Qed.

  End Right.

End ZipWithMap.

Lemma transpose_spec {A r c}(v : r ~> c ~> A) x y : transpose v y x = v x y.
  induction v.
  - case: x; by rewrite /comp to_map //=.
  - case: x; by rewrite zip_pointwise //=.
Qed.

Fixpoint ifeq {A} (th el : A) {s : sort} : s s ~> A :=
  match s with
  | 𝟙fun _const th
  | s1 s2fun xmatch x with
                    | inl x1ifeq th el x1 ++ constant el
                    | inr x2constant el ++ ifeq th el x2
                    end
  end.

Lemma ifeq_spec {A}(th el : A) {s : sort} : (x y : s), ifeq th el x y = if y == x then th else el.
  elim s ⇒ [|s1 IH1 s2 IH2]; movex y; case x; case y; rewrite //=; movez u; by rewrite //= constantE.
Qed.