HVM icon indicating copy to clipboard operation
HVM copied to clipboard

Some rules with variables are not being substituted

Open developedby opened this issue 3 years ago • 2 comments

In some cases where there is more than one rule available for a substitution HVM does not reduce a term even though it should.

Main = @var (Sub var)
(Sub var) = var
(Sub A  ) = B

I expect this to evaluate to @var var, but instead this reduction doesn't occur and the result is @var (Sub var). But removing the second rule,

Main = @var (Sub var)
(Sub var) = var

This now reduces correctly.

If the rules were ordered differently, it would make sense not to reduce since we wouldn't know which path to take. But even in cases where there is no doubt of which rule to take, where i doesn't depend on the value of the variable, this still happens.

Main = @var (Sub var A)
(Sub var A) = var
(Sub B   C) = D

As far as I've tested, the problem only happens when a rule matches a parameter to a variable and then another rule of the same group matches the same parameter to a constructor.

This is causing some problems with the Kind2 type-checker and I think is the cause behind https://github.com/Kindelia/Kind2/issues/38

developedby avatar Aug 10 '22 23:08 developedby

https://github.com/Kindelia/Kind2/issues/38 was not caused by this, but I think this example is:

Rule (a: Nat) (b: Nat): Nat
Rule a         Nat.zero    = a
Rule Nat.zero (Nat.succ b) = Nat.zero

Q (a: Nat) : Equal (Rule a Nat.zero) a
Q a = Equal.refl
Type mismatch.
- Expected: (Equal _0 (Rule a Nat.zero) a)
- Detected: (Equal _0 (Rule a Nat.zero) (Rule a Nat.zero))
Context:
- a : Nat
On 'test.kind2':
   6 | Q a = *Equal.refl*

But,

Rule (a: Nat) (b: Nat): Nat
Rule a         Nat.zero    = a

Q (a: Nat) : Equal (Rule a Nat.zero) a
Q a = Equal.refl

All terms check.

developedby avatar Aug 11 '22 16:08 developedby

The problem is that, by adding the second rule, you make the first argument of Rule strict. That means that Rule a Nat.zero is stuck on the first argument, since it is a variable, not a constructor or a number (i.e., it isn't on weak normal form). That is a consequence of the optimal reduction model used by the HVM. Note that Kind2 type-level computations run on the HVM (via normalization-by-evaluation), so, it follows the same evaluation model.

The solution, thus, for theorem proving purposes, is to treat it like any other stuck variable, and un-stuck it by pattern-matching:

Q (a: Nat) : Equal (Rule a Nat.zero) a
Q Nat.zero     = Equal.refl
Q (Nat.succ b) = Equal.refl

This completes the proof. The same should apply to any instance where this happens.

VictorTaelin avatar Aug 11 '22 17:08 VictorTaelin