Zulip Chat Archive
Stream: general
Topic: Question about unification
Frédéric Tran Minh (Apr 30 2025 at 16:19):
Hi everyone, First, I'm sorry if I do not post at the right place. Here is the question, hope it's not too stupid.
The general context is that I'm trying to generate a definition from a proposition.
Let's consider the following code :
def drec (f : Nat → Nat → Nat) : Nat → Nat
| 0 => 0
| n+1 => f n (drec f n)
theorem t (f : Nat → Nat → Nat) : ∃ g : Nat → Nat, ∀ n :Nat, g (n+1) = f n (g n)
:= ⟨drec f,by intro n ; rfl⟩
noncomputable def u_sub1 :=
Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = n + u n)
noncomputable def u_sub2 :=
Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = (fun m x => m+x) n (u n))
def g1 : Nat → Nat → Nat := fun m x => x+m
def g2 : Nat → Nat → Nat := fun m x => m+x
noncomputable def u_sub3 :=
Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = g1 n (u n))
noncomputable def u_sub4 :=
Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = g2 n (u n))
--noncomputable def u_sub5 :=
-- Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = u n + n)
-- does not typecheck
--noncomputable def u_sub6:=
-- Classical.indefiniteDescription _ (t _ : ∃ u:Nat → Nat , ∀ n:Nat, u (n+1) = (fun m x => x+m) n (u n))
-- does not typecheck
u_sub1, u_sub2, u_sub3, u_sub4 typecheck but u_sub5 and u_sub6 don't.
Why ??
The error message is :
type mismatch
t ?m.580
has type
∃ g, ∀ (n : Nat), g (n + 1) = ?m.580 n (g n) : Prop
but is expected to have type
∃ u, ∀ (n : Nat), u (n + 1) = u n + n : Prop
I'm using Lean v4.15.0
Thanks in advance !
Kyle Miller (Apr 30 2025 at 19:57):
Here's what I've figured so far. The higher-order unification is able to succeed here in a special case (for reasons I don't quite understand). In the following, I'm using refine rfl
to make it be possible to assign to ?f1
even though it's a synthetic opaque metavariable.
example (u : Nat → Nat) (n : Nat) : True := by
have : n + u n = (?f1 : Nat → Nat → Nat) n (u n) := by refine rfl -- succeeds
let f1 := ?f1
-- f1 : Nat → Nat → Nat := HAdd.hAdd
have : u n + n = (?f2 : Nat → Nat → Nat) n (u n) := by refine rfl -- fails
Basically, n + u n
is notation for HAdd.hAdd n (u n)
. Unifying against ?f1 n (u n)
is allowed to succeed here. I'm not sure the rule, but at least we have two expressions with the same arguments, so assigning ?f1
to the function makes some sense.
In the second case, ?f1 (u n) n
doesn't have the same argument order, so that doesn't work anymore.
Last updated: May 02 2025 at 03:31 UTC