Zulip Chat Archive
Stream: general
Topic: Magically assign mvar by unification
Marcus Rossel (Jun 28 2025 at 09:15):
Is there some way to have Lean magically determine a correct value for ?m in the #eval?
import Lean
open Lean Meta Elab Term
inductive Rel where
| eq
| iff
abbrev Rel.dom : Rel → Type _ → Type _
| eq, α => α
| iff, _ => Prop
/-
`Rel.mk` is supposed to represent either `Eq` of `Iff` depending on the value of the `Rel` argument.
That is:
* Rel.mk .eq x y ≡ Eq x y
* Rel.mk .iff p q ≡ Iff p q
-/
abbrev Rel.mk : (rel : Rel) → rel.dom α → rel.dom α → Prop
| eq => Eq
| iff => Iff
/- prints:
e₁: false
e₂: true
-/
#eval do
let tgt ← elabTerm (← `(True = False)) none
let e₁ ← elabTerm (← `(Rel.mk ?m True False)) none
withAssignableSyntheticOpaque do logInfo m!"e₁: {← isDefEq e₁ tgt}"
let e₂ ← elabTerm (← `(Rel.mk .eq True False)) none
withAssignableSyntheticOpaque do logInfo m!"e₂: {← isDefEq e₂ tgt}"
That is, is there a way to get it to print e₁: true?
Mario Carneiro (Jun 28 2025 at 09:36):
that's not normally how unification works, it won't try to guess rel in that context. However, a unification hint might work there
Mario Carneiro (Jun 28 2025 at 09:37):
There are other ways to set it up via typeclasses so that it will work things out in that direction
Mario Carneiro (Jun 28 2025 at 09:49):
class ToRel (α : Type) (rel : outParam Rel) where
relMk : α → α → Prop
relMk_eq : (⟨_, relMk⟩ : Σ α, α → α → Prop) = ⟨rel.dom α, rel.mk⟩
instance : ToRel α .eq where
relMk := Eq
relMk_eq := rfl
instance : ToRel Prop .iff where
relMk := Iff
relMk_eq := rfl
example : ToRel.relMk True False = (True ↔ False) := rfl
example : ToRel.relMk 0 1 = (0 = 1) := rfl
Mario Carneiro (Jun 28 2025 at 09:55):
Here's the unification hint version:
unif_hint (rel : Rel) (α : Type) where rel ≟ .iff ⊢ rel.dom α ≟ Prop
unif_hint (rel : Rel) (α : Type) where rel ≟ .eq ⊢ rel.dom α ≟ α
#check Rel.mk _ True False -- Rel.iff.mk True False : Prop
#check Rel.mk _ 0 1 -- Rel.eq.mk 0 1 : Prop
Marcus Rossel (Jul 04 2025 at 09:14):
Thanks! Unfortunately, the approaches you give don't quite capture the behaviour I need. I don't want Props to always be related by ↔, but instead for the procedure to figure out whether it needs ↔ or = depending on the term it's unifying with. So for example:
example : ToRel.relMk True False = (True = False) := rfl -- fails
... should also work and infer rel := .eq.
(Similar problem when using the given unification hints.)
Last updated: Dec 20 2025 at 21:32 UTC