This PR changes the linear BEq derivation strategy to use `Nat.decEq` instead of `decEq` when comparing constructor indices. Since constructor indices are always `Nat`, using `Nat.decEq` directly is more appropriate because it is `@[reducible]`, whereas the generic `decEq` is only semireducible and does not unfold at `.reducible` transparency. This makes the generated code more transparent-friendly. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
3 KiB
Text
89 lines
3 KiB
Text
module
|
||
-- set_option trace.Elab.Deriving.lawfulBEq true
|
||
-- set_option trace.Meta.MethodSpecs true
|
||
|
||
set_option deriving.beq.linear_construction_threshold 1000
|
||
|
||
inductive L (α : Type u) where
|
||
| nil : L α
|
||
| cons : α → L α → L α
|
||
deriving BEq
|
||
|
||
example {n m : Nat} (h : n = m) :
|
||
(L.cons n (L.nil : L Nat) == L.cons m (L.nil : L Nat)) = true := by
|
||
simp [reduceBEq]
|
||
assumption
|
||
|
||
-- Linear construction
|
||
|
||
namespace Linear
|
||
|
||
set_option deriving.beq.linear_construction_threshold 0
|
||
|
||
inductive L (α : Type u) where
|
||
| nil : L α
|
||
| cons : α → L α → L α
|
||
deriving BEq
|
||
|
||
-- This should still split the equations
|
||
|
||
/--
|
||
info: Linear.instBEqL.beq.eq_1.{u_1} {α✝ : Type u_1} [BEq α✝] (x✝ x✝¹ : L α✝) :
|
||
instBEqL.beq x✝ x✝¹ =
|
||
match x✝.ctorIdx.decEq x✝¹.ctorIdx with
|
||
| isTrue h =>
|
||
match x✝, x✝¹, h with
|
||
| L.nil, L.nil, ⋯ => true
|
||
| L.cons a a_1, L.cons a' a'_1, ⋯ => a == a' && instBEqL.beq a_1 a'_1
|
||
| isFalse h => false
|
||
-/
|
||
#guard_msgs in
|
||
#check instBEqL.beq.eq_1
|
||
|
||
-- And this should work without L.ctorIdx
|
||
|
||
example {n m : Nat} (h : n = m) :
|
||
(L.cons n (L.nil : L Nat) == L.cons m (L.nil : L Nat)) = true := by
|
||
simp [reduceBEq, reduceCtorIdx]
|
||
assumption
|
||
|
||
end Linear
|
||
|
||
-- Module system interactions
|
||
|
||
namespace A
|
||
inductive L where | nil : L | cons : Nat → L → L deriving BEq
|
||
-- NB: Instance, op and theorem are private
|
||
/-- info: @[implicit_reducible] private def A.instBEqL : BEq L -/
|
||
#guard_msgs in #print sig instBEqL
|
||
/-- info: private def A.instBEqL.beq : L → L → Bool -/
|
||
#guard_msgs in #print sig instBEqL.beq
|
||
/-- info: private theorem A.instBEqL.beq_spec_1 : (L.nil == L.nil) = true -/
|
||
#guard_msgs(pass trace, all) in #print sig instBEqL.beq_spec_1
|
||
example : (L.cons n (L.nil : L) == L.cons m (L.nil : L)) ↔ n = m := by simp [reduceBEq]
|
||
end A
|
||
|
||
namespace B
|
||
public inductive L where | nil : L | cons : Nat → L → L deriving BEq
|
||
-- NB: Instance is public and exposed, op and theorem are private
|
||
/-- info: @[implicit_reducible, expose] def B.instBEqL : BEq L -/
|
||
#guard_msgs in #print sig instBEqL
|
||
/-- info: def B.instBEqL.beq : L → L → Bool -/
|
||
#guard_msgs in #print sig instBEqL.beq
|
||
-- NB: Private theorem
|
||
/-- info: private theorem B.instBEqL.beq_spec_1 : (L.nil == L.nil) = true -/
|
||
#guard_msgs(pass trace, all) in #print sig instBEqL.beq_spec_1
|
||
example : (L.cons n (L.nil : L) == L.cons m (L.nil : L)) ↔ n = m := by simp [reduceBEq]
|
||
end B
|
||
|
||
namespace C
|
||
public inductive L where | nil : L | cons : Nat → L → L deriving @[expose] BEq
|
||
-- NB: Public exposed instances, implementation and public theorem
|
||
/-- info: @[implicit_reducible, expose] def C.instBEqL : BEq L -/
|
||
#guard_msgs in #print sig instBEqL
|
||
/-- info: @[expose] def C.instBEqL.beq : L → L → Bool -/
|
||
#guard_msgs in #print sig instBEqL.beq
|
||
/-- info: theorem C.instBEqL.beq_spec_1 : (L.nil == L.nil) = true -/
|
||
#guard_msgs(pass trace, all) in #print sig instBEqL.beq_spec_1
|
||
example : (L.cons n (L.nil : L) == L.cons m (L.nil : L)) ↔ n = m := by simp [reduceBEq]
|
||
end C
|