From 49b04e85eac8c0071f36521e42303af035e4b795 Mon Sep 17 00:00:00 2001 From: Ralf Jung <jung@mpi-sws.org> Date: Wed, 6 Jun 2018 17:13:45 +0200 Subject: [PATCH] add telescopes and a bit of theory about them --- _CoqProject | 2 +- theories/telescopes.v | 128 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 theories/telescopes.v diff --git a/_CoqProject b/_CoqProject index 491ead67..bf320d3d 100644 --- a/_CoqProject +++ b/_CoqProject @@ -42,4 +42,4 @@ theories/sorting.v theories/infinite.v theories/nat_cancel.v theories/namespaces.v - +theories/telescopes.v diff --git a/theories/telescopes.v b/theories/telescopes.v new file mode 100644 index 00000000..c12358e5 --- /dev/null +++ b/theories/telescopes.v @@ -0,0 +1,128 @@ +From stdpp Require Import base tactics. +Set Default Proof Using "Type". + +(** Telescopes *) +Inductive tele : Type := + | TeleO : tele + | TeleS {X} (binder : X → tele) : tele. + +Arguments TeleS {_} _. + +(** The telescope version of Coq's function type *) +Fixpoint tele_fun (TT : tele) (T : Type) : Type := + match TT with + | TeleO => T + | TeleS b => ∀ x, tele_fun (b x) T + end. + +Notation "TT -t> A" := + (tele_fun TT A) (at level 99, A at level 200, right associativity). + +(** An eliminator for elements of [tele_fun]. + We use a [fix] because, for some reason, that makes stuff print nicer + in the proofs in iris:bi/lib/telescopes.v *) +Definition tele_fold {X Y} {TT : tele} (step : ∀ {A : Type}, (A → Y) → Y) (base : X → Y) + : (TT -t> X) → Y := + (fix rec {TT} : (TT -t> X) → Y := + match TT as TT return (TT -t> X) → Y with + | TeleO => λ x : X, base x + | TeleS b => λ f, step (λ x, rec (f x)) + end) TT. +Arguments tele_fold {_ _ !_} _ _ _ /. + +(** A sigma-like type for an "element" of a telescope, i.e. the data it + takes to get a [T] from a [TT -t> T]. *) +Inductive tele_arg : tele → Type := +| TargO : tele_arg TeleO +(* the [x] is the only relevant data here *) +| TargS {X} {binder} (x : X) : tele_arg (binder x) → tele_arg (TeleS binder). + +Definition tele_app {TT : tele} {T} (f : TT -t> T) : tele_arg TT → T := + λ a, (fix rec {TT} (a : tele_arg TT) : (TT -t> T) → T := + match a in tele_arg TT return (TT -t> T) → T with + | TargO => λ t : T, t + | TargS x a => λ f, rec a (f x) + end) TT a f. +Arguments tele_app {!_ _} _ !_ /. + +Coercion tele_arg : tele >-> Sortclass. +Coercion tele_app : tele_fun >-> Funclass. + +(** Inversion lemma for [tele_arg] *) +Lemma tele_arg_inv {TT : tele} (a : TT) : + match TT as TT return TT → Prop with + | TeleO => λ a, a = TargO + | TeleS f => λ a, ∃ x a', a = TargS x a' + end a. +Proof. induction a; eauto. Qed. +Lemma tele_arg_O_inv (a : TeleO) : a = TargO. +Proof. exact (tele_arg_inv a). Qed. +Lemma tele_arg_S_inv {X} {f : X → tele} (a : TeleS f) : + ∃ x a', a = TargS x a'. +Proof. exact (tele_arg_inv a). Qed. + +(** Map below a tele_fun *) +Fixpoint tele_map {T U} {TT : tele} : (T → U) → (TT -t> T) → TT -t> U := + match TT as TT return (T → U) → (TT -t> T) → TT -t> U with + | TeleO => λ F : T → U, F + | @TeleS X b => λ (F : T → U) (f : TeleS b -t> T) (x : X), + tele_map F (f x) + end. +Arguments tele_map {_ _ !_} _ _ /. + +Lemma tele_map_app {T U} {TT : tele} (F : T → U) (t : TT -t> T) (x : TT) : + (tele_map F t) x = F (t x). +Proof. + induction TT as [|X f IH]; simpl in *. + - rewrite (tele_arg_O_inv x). done. + - destruct (tele_arg_S_inv x) as [x' [a' ->]]. simpl. + rewrite <-IH. done. +Qed. + +Global Instance tele_fmap {TT : tele} : FMap (tele_fun TT) := λ T U, tele_map. + +Lemma tele_fmap_app {T U} {TT : tele} (F : T → U) (t : TT -t> T) (x : TT) : + (F <$> t) x = F (t x). +Proof. apply tele_map_app. Qed. + +Global Instance tele_fmap2 {TT1 TT2 : tele} : FMap (tele_fun TT1 ∘ tele_fun TT2) := + λ T U, tele_map ∘ tele_map. + +Lemma tele_fmap2_app {T U} {TT1 TT2 : tele} (F : T → U) (t : TT1 -t> TT2 -t> T) + (x : TT1) (y : TT2) : + (F <$> t) x y = F (t x y). +Proof. + unfold fmap, tele_fmap2. simpl. + rewrite !tele_map_app. done. +Qed. + +(** Operate below [tele_fun]s with argument telescope [TT]. *) +Fixpoint tele_bind {U} {TT : tele} : (TT → U) → TT -t> U := + match TT as TT return (TT → U) → TT -t> U with + | TeleO => λ F, F TargO + | @TeleS X b => λ (F : TeleS b → U) (x : X), (* b x -t> U *) + tele_bind (λ a, F (TargS x a)) + end. +Arguments tele_bind {_ !_} _ /. + +(** A function that looks funny. *) +Definition tele_arg_id (TT : tele) : TT -t> TT := tele_bind id. + +(** Notation *) +Notation "'[tele' x .. z ]" := + (TeleS (fun x => .. (TeleS (fun z => TeleO)) ..)) + (x binder, z binder, format "[tele '[hv' x .. z ']' ]"). +Notation "'[tele' ]" := (TeleO) + (format "[tele ]"). + +Notation "'[tele_arg' x ; .. ; z ]" := + (TargS x ( .. (TargS z TargO) ..)) + (format "[tele_arg '[hv' x ; .. ; z ']' ]"). +Notation "'[tele_arg' ]" := (TargO) + (format "[tele_arg ]"). + +(** Notation-compatible telescope mapping *) +Notation "'λ..' x .. y , e" := + (tele_app $ tele_bind (λ x, .. (tele_app $ tele_bind (λ y, e)) .. )) + (at level 200, x binder, y binder, right associativity, + format "'[ ' 'λ..' x .. y ']' , e"). -- GitLab