Tealeaves.Backends.Adapters.DBtoLN
(*|
##############################
Translating between locally nameless and de Bruijn indices
##############################
We reason about a translation between syntax with de Bruijn indices
and locally nameless variables. This consists of a function which,
given a locally closed term t, outputs a term of the same shape whose
leaves are de Bruijn indices and a "key": some arbitrary permutation
of the names of free variables in t. Another function accepts a key
and a de Bruijn term and computes a locally nameless term of the same
shape. The two functions are shown to be inverses.
.. contents:: Table of Contents :depth: 2
============================
Imports and setup
============================
Since we are using the Kleisli typeclass hierarchy, we import modules
under the namespaces ``Classes.Kleisli`` and ``Theory.Kleisli.``
|*)
From Tealeaves Require Export
Backends.LN
Backends.DB.DB
Backends.Adapters.Key
Classes.Kleisli.DecoratedTraversableMonad
Functors.Option.
Import DecoratedTraversableMonad.UsefulInstances.
#[local] Generalizable Variables W T U.
#[local] Open Scope nat_scope.
(*|
============================
Operations
============================
|*)
Definition toLN_loc (k: key) '(depth, ix) : option LN :=
if bound_b ix depth == true
then
Some (Bd ix)
else
map (F := option) Fr (getName k (ix - depth)).
Definition toLN
`{Mapdt_inst: Mapdt nat T} (k: key): T nat → option (T LN) :=
mapdt (G := option) (toLN_loc k).
(*|
============================
Theory
============================
|*)
Section theory.
Context
`{Return_T: Return T}
`{Map_T: Map T}
`{Bind_TT: Bind T T}
`{Traverse_T: Traverse T}
`{Mapd_T: Mapd nat T}
`{Bindt_TT: Bindt T T}
`{Bindd_T: Bindd nat T T}
`{Mapdt_T: Mapdt nat T}
`{Binddt_TT: Binddt nat T T}
`{! Compat_Map_Binddt nat T T}
`{! Compat_Bind_Binddt nat T T}
`{! Compat_Traverse_Binddt nat T T}
`{! Compat_Mapd_Binddt nat T T}
`{! Compat_Bindt_Binddt nat T T}
`{! Compat_Bindd_Binddt nat T T}
`{! Compat_Mapdt_Binddt nat T T}.
Context
`{Monad_inst: ! DecoratedTraversableMonad nat T}.
Context
`{Map_U: Map U}
`{Bind_TU: Bind T U}
`{Traverse_U: Traverse U}
`{Mapd_U: Mapd nat U}
`{Bindt_TU: Bindt T U}
`{Bindd_TU: Bindd nat T U}
`{Mapdt_U: Mapdt nat U}
`{Binddt_TU: Binddt nat T U}
`{! Compat_Map_Binddt nat T U}
`{! Compat_Bind_Binddt nat T U}
`{! Compat_Traverse_Binddt nat T U}
`{! Compat_Mapd_Binddt nat T U}
`{! Compat_Bindt_Binddt nat T U}
`{! Compat_Bindd_Binddt nat T U}
`{! Compat_Mapdt_Binddt nat T U}.
Context
`{Module_inst: ! DecoratedTraversableRightPreModule nat T U
(unit := Monoid_unit_zero)
(op := Monoid_op_plus)}.
Lemma toLN_loc_None_iff:
∀ k d n, toLN_loc k (d, n) = None ↔ n ≥ d ∧ ¬ (n - d < length k).
Proof.
intros.
unfold toLN_loc.
unfold bound_b, bound_within_b.
replace (d + 0) with d by lia.
remember (Nat.ltb n d) as b.
symmetry in Heqb.
destruct b.
- cbn.
rewrite PeanoNat.Nat.ltb_lt in Heqb.
split; intro contra.
+ exfalso. inversion contra.
+ exfalso. lia.
- cbn.
rewrite PeanoNat.Nat.ltb_ge in Heqb.
rewrite map_None_eq_iff.
rewrite <- key_lookup_ix_None_iff.
unfold contains_ix_upto.
split; now auto.
Qed.
Lemma toLN_None_iff:
∀ k (t: U nat), toLN k t = None ↔ ¬ cl_at (length k) t.
Proof.
intros.
rewrite cl_at_spec_not.
unfold toLN.
rewrite mapdt_option_None_spec.
setoid_rewrite toLN_loc_None_iff.
unfold cl_at_loc, bound_within.
split; intros [e [a [Hin Hspec]]].
- ∃ e. ∃ a; split; auto. lia.
- ∃ e. ∃ a; split; auto. lia.
Qed.
End theory.
##############################
Translating between locally nameless and de Bruijn indices
##############################
We reason about a translation between syntax with de Bruijn indices
and locally nameless variables. This consists of a function which,
given a locally closed term t, outputs a term of the same shape whose
leaves are de Bruijn indices and a "key": some arbitrary permutation
of the names of free variables in t. Another function accepts a key
and a de Bruijn term and computes a locally nameless term of the same
shape. The two functions are shown to be inverses.
.. contents:: Table of Contents :depth: 2
============================
Imports and setup
============================
Since we are using the Kleisli typeclass hierarchy, we import modules
under the namespaces ``Classes.Kleisli`` and ``Theory.Kleisli.``
|*)
From Tealeaves Require Export
Backends.LN
Backends.DB.DB
Backends.Adapters.Key
Classes.Kleisli.DecoratedTraversableMonad
Functors.Option.
Import DecoratedTraversableMonad.UsefulInstances.
#[local] Generalizable Variables W T U.
#[local] Open Scope nat_scope.
(*|
============================
Operations
============================
|*)
Definition toLN_loc (k: key) '(depth, ix) : option LN :=
if bound_b ix depth == true
then
Some (Bd ix)
else
map (F := option) Fr (getName k (ix - depth)).
Definition toLN
`{Mapdt_inst: Mapdt nat T} (k: key): T nat → option (T LN) :=
mapdt (G := option) (toLN_loc k).
(*|
============================
Theory
============================
|*)
Section theory.
Context
`{Return_T: Return T}
`{Map_T: Map T}
`{Bind_TT: Bind T T}
`{Traverse_T: Traverse T}
`{Mapd_T: Mapd nat T}
`{Bindt_TT: Bindt T T}
`{Bindd_T: Bindd nat T T}
`{Mapdt_T: Mapdt nat T}
`{Binddt_TT: Binddt nat T T}
`{! Compat_Map_Binddt nat T T}
`{! Compat_Bind_Binddt nat T T}
`{! Compat_Traverse_Binddt nat T T}
`{! Compat_Mapd_Binddt nat T T}
`{! Compat_Bindt_Binddt nat T T}
`{! Compat_Bindd_Binddt nat T T}
`{! Compat_Mapdt_Binddt nat T T}.
Context
`{Monad_inst: ! DecoratedTraversableMonad nat T}.
Context
`{Map_U: Map U}
`{Bind_TU: Bind T U}
`{Traverse_U: Traverse U}
`{Mapd_U: Mapd nat U}
`{Bindt_TU: Bindt T U}
`{Bindd_TU: Bindd nat T U}
`{Mapdt_U: Mapdt nat U}
`{Binddt_TU: Binddt nat T U}
`{! Compat_Map_Binddt nat T U}
`{! Compat_Bind_Binddt nat T U}
`{! Compat_Traverse_Binddt nat T U}
`{! Compat_Mapd_Binddt nat T U}
`{! Compat_Bindt_Binddt nat T U}
`{! Compat_Bindd_Binddt nat T U}
`{! Compat_Mapdt_Binddt nat T U}.
Context
`{Module_inst: ! DecoratedTraversableRightPreModule nat T U
(unit := Monoid_unit_zero)
(op := Monoid_op_plus)}.
Lemma toLN_loc_None_iff:
∀ k d n, toLN_loc k (d, n) = None ↔ n ≥ d ∧ ¬ (n - d < length k).
Proof.
intros.
unfold toLN_loc.
unfold bound_b, bound_within_b.
replace (d + 0) with d by lia.
remember (Nat.ltb n d) as b.
symmetry in Heqb.
destruct b.
- cbn.
rewrite PeanoNat.Nat.ltb_lt in Heqb.
split; intro contra.
+ exfalso. inversion contra.
+ exfalso. lia.
- cbn.
rewrite PeanoNat.Nat.ltb_ge in Heqb.
rewrite map_None_eq_iff.
rewrite <- key_lookup_ix_None_iff.
unfold contains_ix_upto.
split; now auto.
Qed.
Lemma toLN_None_iff:
∀ k (t: U nat), toLN k t = None ↔ ¬ cl_at (length k) t.
Proof.
intros.
rewrite cl_at_spec_not.
unfold toLN.
rewrite mapdt_option_None_spec.
setoid_rewrite toLN_loc_None_iff.
unfold cl_at_loc, bound_within.
split; intros [e [a [Hin Hspec]]].
- ∃ e. ∃ a; split; auto. lia.
- ∃ e. ∃ a; split; auto. lia.
Qed.
End theory.