Zulip Chat Archive

Stream: new members

Topic: autoProp on OfNat instance


MrQubo (Feb 03 2025 at 18:36):

I've made a structure family Idx n that represent numbers less than n:

structure Idx (n : ) where
  val : 
  property : val < n := by simp_all_arith <;> omega

Now, I wanted to define na instance of OfNat for this type. But, because of how this type is defined, I cannot define an instance of OfNat (Idx n) i for any i, only for i s.t. i < n. However, I don't know how to do that.

I've tried like this:

instance {n i} (_ : i < n := by simp_all_arith <;> omega) : OfNat (Idx n) i where
  ofNat := { val := i }

This instance does compile, but it doesn't seem to work. This code still raises an error:

def x : Idx 3 := 2

failed to synthesize OfNat (Idx 3) 2

Instance of OfNat (Fin n) i avoids this problem by defining instance for every i. Maybe it's currently not possible to do what I want in Lean?

Ruben Van de Velde (Feb 03 2025 at 18:38):

Oh yeah, you can't write an instance with a hypothesis like that

Markus Himmel (Feb 03 2025 at 18:45):

There is a trick due to Gabriel Ebner:

structure Idx (n : Nat) where
  val : Nat
  property : val < n := by simp_all_arith <;> omega

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

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

instance {n i} [h : When (i < n)] : OfNat (Idx n) i where
  ofNat := { val := i, property := h.isTrue }

def x : Idx 3 := 2 -- works
def y : Idx 3 := 3 -- fails

But it's not exactly supported, and you can't have it use simp_all_arith <;> omega, only decide.

MrQubo (Feb 03 2025 at 19:14):

I think I was able to implement what I want using macro:

import Mathlib

def idxOfNum {n} (i : ) (_ : i < n := by simp_all_arith <;> omega) : Idx n :=
  i, i < n›⟩

syntax (name := idxn) num : term

macro_rules (kind := idxn)
  | `($i:num) => `(idxOfNum $i)

def x : Idx 3 := 2
def y :  := 2
#check_failure (3 : Idx 3)

Last updated: May 02 2025 at 03:31 UTC