Zulip Chat Archive

Stream: lean4

Topic: partial recursive def: failed to show inhabited non empty


Andrés Goens (Jul 29 2022 at 10:56):

We're getting an issue with @An Qi Zhang where we have a definition that's marked as partial (because it is pretty complex to show termination) and recursive, but works by translating from one recursive type into a different recursive type. Lean won't compile it stating failed to compile partial definition 'someFunction', failed to show that type is inhabited and non empty. Here's an MWE:

inductive Foo
  | foo1 : Foo
  | foo2 : Foo  Foo

inductive Bar
  | bar1 : Bar
  | bar2 : Bar  Bar

partial def footobar : Foo  Bar
  | .foo1 => Bar.bar1
  | .foo2 f => footobar f

In this MWE, if we remove partial Lean can figure out the WF recursion and is happy to accept it, but in our real case it's not that simple. I imagine then marking footobar as partial here shouldn't produce that error though, right?

Henrik Böving (Jul 29 2022 at 11:04):

This is due to the implementation of partial, what Lean will do internally is translate this into an opaque footobar : Foo -> Bar with an implementedBy attribute pointing to an unsafe def that contains your actual code. in order for opaque footobar to be valid you have to provide proof that the type is inhabited, otherwise you are basically writing an axiom. So what you have to do here is:

inductive Foo
  | foo1 : Foo
  | foo2 : Foo  Foo

inductive Bar
  | bar1 : Bar
  | bar2 : Bar  Bar
  deriving Inhabited

partial def footobar : Foo  Bar
  | .foo1 => Bar.bar1
  | .foo2 f => footobar f

Henrik Böving (Jul 29 2022 at 11:27):

The argument for why this is a correct error to do is that basically your unsafe def can do whatever it wants and magically produce terms of arbitrary type out of thin air with unsafe cast operations which could corrupt consistency of the system if the resulting type wasn't shown to be inhabited in a safe way.


Last updated: Dec 20 2023 at 11:08 UTC