lambdapi icon indicating copy to clipboard operation
lambdapi copied to clipboard

higher-order rewrite rule with implicit arguments under the binder: uninformative cryptic error message? BUG?

Open 1337777 opened this issue 1 year ago • 2 comments

higher-order rewrite rule with implicit arguments under the binder: uninformative cryptic error message? BUG?

MINIMAL EXAMPLE with the solution (could be non-obvious in real-world complex code). Then an alternative solution (optional), specific to the subject matter, in the style of Kosta Dosen.

constant symbol cat : TYPE;
constant symbol Terminal_cat : cat;

constant symbol func : Π (A B : cat), TYPE;
constant symbol Id_func : Π [A : cat], func A A;
symbol ∘> : Π [A B C: cat], func A B → func B C → func A C;
notation ∘> infix left 90; // ∘>  is a reducible symbols with rules that compute it

constant symbol Set  : TYPE;
injective symbol τ : Set → TYPE;
constant symbol set_cat : Set → cat;

constant symbol set_cat_intro_func : Π [I : Set], τ I → func Terminal_cat (set_cat I); 
injective symbol set_cat_elim_func : Π [I : Set] [A : cat], (τ I → func Terminal_cat A ) → func (set_cat I) A;

// usual beta rule

//OK
rule  set_cat_elim_func (set_cat_intro_func) ↪ Id_func;

// but the extensional form of above beta rule is often required, it now uses higher-order rewrite rule/unification:

// KO
// "Bug. Introduced symbol [$15227] cannot be removed. Please contact the developers."
rule set_cat_elim_func (λ i, set_cat_intro_func i) ↪ Id_func;

// PROBLEM: THE ERROR MESSAGE HERE IS NOT VERY INFORMATIVE ABOUT WHAT IS THE PROBLEM AND HOW TO SOLVE IT

// SOLUTION:

// OK
rule set_cat_elim_func (λ i, @set_cat_intro_func $I.[] i) ↪ Id_func;


// --------8<------OPTIONAL PART---------->8--------

// ALTERNATIVE SOLUTION: 
// avoid higher-order rewrite rule unification and use Kosta Dosen techniques:

// in fact, putting aside the minimal example which demonstrates the "BUG"
// Here is the REAL INTENTION  behind all of that:

// The REAL INTENTION MOTIVATION was to have this (too complex) rewrite rule
// which is second-order unifification and it has some inner-and-under-binder reducible symbols `∘>` 
// So this assumes that the Lambdapi logical framework has such higher-order rewrite rules,

rule set_cat_elim_func (λ i, (@set_cat_intro_func $I.[] i) ∘> $G.[]) ↪ $G;

// but in case Lambdapi was not that powerful, there would still exists an alternative:

// KOSTA DOSEN ALTERNATIVE SOLUTION

injective symbol set_cat_intro_func_ALT : Π [I : Set] [A : cat], func (set_cat I) A → (τ I → func Terminal_cat A); 

// naturality (accumulation), which says that morally : the new (set_cat_intro_func_ALT F i) is the former ((set_cat_intro_func i) ∘> $F).
rule (set_cat_intro_func_ALT $F $i) ∘> $G ↪ set_cat_intro_func_ALT ($F ∘> $G) $i;

//alternative beta rule, fist-order and no inner reducible symbols inside the rule
rule @set_cat_elim_func $I _ (λ i, @∘> $A.[] $B.[] $C.[] (@set_cat_intro_func $I.[] i)  $G.[]) ↪ $G; //nasty: second-order unif & inner-and-under-binder reducible symbols

rule  set_cat_elim_func (set_cat_intro_func_ALT $F) ↪ $F;


1337777 avatar Dec 11 '24 15:12 1337777

If you print implicit arguments (flag "print_implicits" on) and the rules of set_cat_elim_func (print set_cat_elim_func), you see that the first rule actually is:

rule @set_cat_elim_func $0 $1 (@set_cat_intro_func $2) ↪ @Id_func (set_cat $0);

When adding an abstraction, you can specify how each pattern variable that is below the abstraction depends on it. By default, a pattern depends on all abstracted variables. The user manual indicates: "The unnamed pattern variable _ is always the most general: if x and y are the only variables in scope, then _ is equivalent to $_.[x;y]." This means that the second rule is like:

rule @set_cat_elim_func $0 $1 (λ i, @set_cat_intro_func $2.[i] i) ↪ @Id_func (set_cat $0);

but the type of i then is τ $2.[i], which is problematic (a term t whose type contains t itself).

Indeed, the solution is to enforce $2 to not depend on i and explicitly write $2.[].

We should definitely improve the error message. The code currently contains the following comment: "A symbol may also come from a metavariable that appeared in the type of a metavariable that was replaced by a symbol. We do not have concrete examples of that happening yet." We now have one. Thank you.

Remark: using flag "eta_equality" on doesn't help (eta-conversion is only used when comparing an abstraction with some other term). Lambdapi implements no eta-reduction (or eta-expansion). This could be a feature request. With eta-reduction, the second rule would be useless though.

Comment: it is unusual to define an arrow type constructor as infix left.

fblanqui avatar Dec 11 '24 20:12 fblanqui

The arrow/function type constructor is

constant symbol func : Π (A B : cat), TYPE;

the composition of elements/functions in this arrow type is

symbol ∘> : Π [A B C: cat], func A B → func B C → func A C;

with a rewrite rule

`rule $X ∘> ($G ∘> $H) ↪ ($X ∘> $G) ∘> $H;

so that (x ∘> f ) ∘> g means the usual textbook notation g ∘ (f ∘ x)

so the notation

notation ∘> infix left 90;

is clearly justified by the rewrite rule which associates to the left, which itself is justified by the intended operational meaning of composing/applying inputs to inner functions until the last outer function to get an output

1337777 avatar Dec 24 '24 22:12 1337777