Zulip Chat Archive

Stream: lean4

Topic: Unify level mvars


Marcus Rossel (Jan 19 2024 at 19:18):

I was hoping I could use isDefEq to unify level mvars, but apparently this doesn't work:

import Lean
open Lean Meta

-- Eq.{?_uniq.1061}
#eval do
  let e₁ := Expr.const `Eq [1]
  let e₂  mkConstWithFreshMVarLevels `Eq
  unless  isDefEq e₁ e₂ do throwError "not defeq"
  return e₂

What would be the right approach here?

Marcus Rossel (Jan 19 2024 at 19:26):

Ah, as always the solution was instantiateMVars e₂.

Notification Bot (Jan 19 2024 at 19:26):

Marcus Rossel has marked this topic as resolved.

Notification Bot (Jan 19 2024 at 19:39):

Marcus Rossel has marked this topic as unresolved.

Marcus Rossel (Jan 19 2024 at 19:39):

Actually, in this example even instantiating mvars doesn't help:

import Lean
open Lean Meta

#eval do -- OfNat.ofNat.{?_uniq.1} Nat (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) instOfNatNat.{0}
  let u  mkFreshLevelMVar
  let e₁ := mkAppN (.const `OfNat.ofNat [0]) #[(.const `Nat []), (mkNatLit 0), (.const `instOfNatNat [0])]
  let e₂ := mkAppN (.const `OfNat.ofNat [u]) #[(.const `Nat []), (mkNatLit 0), (.const `instOfNatNat [0])]
  unless  isDefEq e₁ e₂ do throwError "not defeq"
  let e₂'  instantiateMVars e₂
  IO.println e₂'

Kyle Miller (Jan 19 2024 at 20:06):

isDefEq assumes that your expressions are well-typed. I wouldn't be surprised if it's skipping steps it knows it can skip with this assumption.

Kyle Miller (Jan 19 2024 at 20:07):

How are you in this situation where you have a metavariable in an expression like that, where it's not already constrained by the other arguments?

Kyle Miller (Jan 19 2024 at 20:08):

By the way, docs#Lean.mkNatLit is how you make a natlit expression for Nat

Kyle Miller (Jan 19 2024 at 20:09):

There's also docs#Lean.Meta.mkNumeral for general types

Marcus Rossel (Jan 19 2024 at 23:19):

Kyle Miller said:

How are you in this situation where you have a metavariable in an expression like that, where it's not already constrained by the other arguments?

I'm using an external solver to generate a sequence of rewrites for a proof, and the expression language of that external solver doesn't have a notion universe levels. Now I'm trying to reconstruct Lean expressions from those external expression and my idea was to fill in the missing pieces with mvars which can then all be inferred during further steps.
Is there some other way to tell Lean to figure out the level mvars? Or is this not generally possible?

Eric Wieser (Jan 20 2024 at 01:20):

I was expecting instantiateLevelMVars to help here, but it doesn't seem to


Last updated: May 02 2025 at 03:31 UTC