Zulip Chat Archive

Stream: lean4

Topic: Structure with noncomputable rec/accessor?


James Gallicchio (Sep 13 2022 at 17:58):

Is there a way to mark a structure's rec/accessor functions noncomputable after the declaration? I'm doing some FFI stuff, I would like them to be available for reasoning, but noncomputable. My first instinct was to use the attribute command but noncomputable isn't actually an attribute.

James Gallicchio (Sep 13 2022 at 21:05):

Ended up just making an opaque NonemptyType and introducing the axioms I needed, but I'm still curious if this solution is possible!

Gabriel Ebner (Sep 14 2022 at 09:43):

Can you post a concrete example of what you're trying to do?

cognivore (Sep 14 2022 at 18:29):

:eyes:

James Gallicchio (Sep 14 2022 at 20:19):

Sure -- the reason for the noncomputability is to do with this Uninit type @Mario Carneiro worked out, which is defined as follows:

opaque UninitPointed.{u} (α : Type u) : NonemptyType.{u}
def Uninit.{u} (α : Type u) : Type u := (UninitPointed α).type

namespace Uninit

instance : Nonempty (Uninit α) := (UninitPointed α).property

noncomputable opaque uninit {α} : Uninit α

unsafe def initUnsafe (a : α) : Uninit α := unsafeCast a
@[implementedBy initUnsafe]
opaque init (a : α) : Uninit α

...

def getValueExists (x : Uninit α) (h :  a, x = .init a) : α := ...

So given a value x : Uninit α it is undecidable whether it is init or uninit. But given a proof that ∃ a, x = Uninit.init a the value can be synthesized.

James Gallicchio (Sep 14 2022 at 20:23):

All that said, an uninitialized value of type Uninit α violates the Lean ABI (in particular, something might call lean_inc or lean_dec on it, which could segfault). So, Uninit α values can only exist if they are contained by some external object that properly handles them

James Gallicchio (Sep 14 2022 at 20:28):

That's okay for me -- I wanted to use Uninit α to implement arrays that can be partially uninitialized. The uninit values are never actually exposed to the Lean runtime, but are used to define the interface. So I wanted to have something like this:

structure ArrayUninit.{u} (α : Type u) (n : Nat) where
  data : Fin n  Uninit α

But, of course, this is potentially unsafe if data is computable, since then we could actually expose uninitialized values to the runtime.

James Gallicchio (Sep 14 2022 at 20:30):

So since I couldn't figure out how to do that, instead I wrote a new opaque type that is isomorphic to Fin n → Uninit α. I had to then manually axiomatize the reasoning principles for it, which are equivalent to what would be auto-generated by the structure, modulo rec being noncomputable.


Last updated: Dec 20 2023 at 11:08 UTC