Zulip Chat Archive

Stream: metaprogramming / tactics

Topic: Reduce during typeclass search


Markus de Medeiros (May 26 2025 at 21:05):

Is there some way to make Lean reduce terms while doing typeclass search? I was doing some logic programming using typeclasses, for no real reason aside from seeing if it was possible, and was wondering if there was some hidden option somewhere which might make the typechecker reduce before it looks for matching instances?

class Reflect (b : outParam Bool) where is_true : b
instance : Reflect true :=  rfl 
#synth Reflect (5 == 5) -- It can synthesize an instance for Reflect (5 == 5) when it reduces first

class ReflectClient (n1 n2 : Nat) where
instance {n1 n2 : Nat} [Reflect (n1 == n2)] : ReflectClient n1 n2 where

-- set_option trace.Meta.synthInstance true
-- check #synth ReflectClient 5 5
-- [Meta.synthInstance] ❌️ ReflectClient 5 5
--   [Meta.synthInstance] new goal ReflectClient 5 5
--     [Meta.synthInstance.instances] #[@instReflectClientOfReflectBeqNat]
--   [Meta.synthInstance] ✅️ apply @instReflectClientOfReflectBeqNat to ReflectClient 5 5
--     [Meta.synthInstance.tryResolve] ✅️ ReflectClient 5 5 ≟ ReflectClient 5 5
--     [Meta.synthInstance] no instances for Reflect (5 == 5)   -- Doesn't reduce so doesn't find an instance
--       [Meta.synthInstance.instances] #[]
--   [Meta.synthInstance] result <not-available>

Robin Arnez (May 27 2025 at 05:53):

Two things are needed here:

  1. instance : Reflect (no_index true) := ⟨rfl⟩. Without no_index it will only consider this instance if it's already true before reduction
  2. Use more reducible functions like n1.beq n2

I have honestly no clue why the first one succeeded lol

Robin Arnez (May 27 2025 at 05:54):

I think the first one succeeding is not typeclass search doing something but the #synth command doing something special

Kyle Miller (May 27 2025 at 06:02):

Gabriel Ebner pointed out this trick awhile ago:

class When (p : Prop) [Decidable p] : Prop where
  isTrue : p

instance : @When p (.isTrue h) := @When.mk p (.isTrue h) h

This allows adding [When (m < n)] instances for example.

This works because Lean does more reduction for implicit arguments. Maybe you can make use of this somehow?

Robin Arnez (May 27 2025 at 06:06):

This needs no_index as well though, no?

Robin Arnez (May 27 2025 at 06:06):

Hmm no? Weird

Robin Arnez (May 27 2025 at 06:07):

Oh it's an instance argument

Robin Arnez (May 27 2025 at 06:07):

Yeah, makes sense

Edward van de Meent (May 27 2025 at 11:17):

this seems similar to Fact for some reason...

Edward van de Meent (May 27 2025 at 11:19):

but i guess it's different (crucially for this topic) due to the instance argument in the type

Markus de Medeiros (May 28 2025 at 12:29):

The When trick seems to work! Super clever, thanks all :)


Last updated: Dec 20 2025 at 21:32 UTC