Zulip Chat Archive
Stream: general
Topic: Case split on prop
Patrick Stevens (Aug 11 2024 at 15:09):
Here's something that doesn't work:
import Batteries.Data.Nat.Basic
def position_of (elt : List.Mem 3 [4,3,6]) : Nat :=
match elt with
| .head _ => sorry
| .tail _ => sorry
The head
block does not type check - of course it can't! - and this prevents compilation. How can I access the fact that List.Mem
knows where the 3
is?
The XY of this is that I want to convert this function so that it outputs data rather than a Prop: I want to know which k
it found, along with a proof that the k
has the property. (Changing the "exists" to a Sum
fails because the equality proof is a Prop.) I think it should be possible to do this without any need to decide equality, because Mem
already knows where the element is.
import Batteries.Data.Nat.Basic
import Batteries.Data.List.Basic
import Mathlib.Tactic.Use
def hits'
{m : Nat} {B : Type}
(f : Fin m → B)
{r : B} {n i : Nat} {pr : n + i = m}
(elt : List.Mem r (List.ofFn.go f n i pr))
: ∃ k, f k = r
:= by
match n with
| 0 =>
exfalso
unfold List.ofFn.go at elt
exact (List.mem_nil_iff r).mp elt
| n + 1 =>
rcases elt with _ | ⟨_, isMem⟩
· use ⟨i, by omega⟩
· exact @hits' m B f r n (i + 1) (by omega) isMem
Henrik Böving (Aug 11 2024 at 15:25):
List.Mem does not actually know where 3 is. Lean erases propositions at compile time so you cannot create any data (i.e. anything that is not a proposition) from a proposition. You can encode Membership in a way that lives in Type
and explicitly tracks the index at which the element is but that is not possible with the built in List.Mem
.
Patrick Stevens (Aug 11 2024 at 15:38):
Ah right - is the reason List.Mem
was defined as a Prop simply runtime efficiency, or does Prop have any other benefits to outweigh the fact that it's harder to compute with?
Henrik Böving (Aug 11 2024 at 15:40):
Proof irrelvance also helps doing other proofs, e.g. when proving equality of subtypes etc. There is just, not much of a reason to define it not as Prop
I think.
Kyle Miller (Aug 11 2024 at 15:45):
You can make a function that, using DecidableEq
and a membership proof, gives you the first index.
Kyle Miller (Aug 11 2024 at 15:47):
This sort of fits the bill: docs#List.indexOf_lt_length
Patrick Stevens (Aug 11 2024 at 15:48):
The annoying part of that is I'm doing this so as to prove that Mathlib.ModelTheory.Syntax
's Term
has decidable equality; this is the recursive case, Term.func f (vars : Fin n -> Term)
, and I don't trivially have access to the proof of decidability yet
Patrick Stevens (Aug 11 2024 at 15:49):
Somewhere in my proof I have implicitly computed the index, I just need to thread it through a bunch of functions (and I was hoping it could be derived from the Mem
instead)
Kyle Miller (Aug 11 2024 at 15:57):
Maybe you could use the type {n : Nat // lst.get? n = v}
instead, or something like it?
Patrick Stevens (Aug 11 2024 at 17:04):
Thanks, that's working out well I think and is a very simple change!
Last updated: May 02 2025 at 03:31 UTC