Zulip Chat Archive
Stream: general
Topic: Recursion through `Array`
Joachim Breitner (Oct 26 2023 at 14:01):
How would I define this function without using partial
:
inductive T : Type where
| mk : Array T -> T
partial def T.size : T → Nat
| .mk cs => cs.foldl (init := 0) fun n c => n + c.size
My best bet would be to assume we have a Array.attach
like docs#List.attach and do something like
inductive T : Type where
| mk : Array T -> T
opaque Array.attach : (a : Array α) → Array ({ x : α // x ∈ a.data })
def T.size : T → Nat
| .mk cs => cs.attach.foldl (init := 0) fun n ⟨c,hc⟩ => n + c.size
termination_by _ t => sizeOf t
(which doesn’t work yet but I believe I could make it work) but I wonder if there is a better direction.
Arthur Adjedj (Oct 26 2023 at 15:43):
(deleted)
Joachim Breitner (Oct 26 2023 at 16:02):
Here is a way that seems to work:
inductive T : Type where
| mk : Array T -> T
opaque Array.attach {α} : (a : Array α) → Array ({ x : α // x ∈ a.data })
@[simp]
theorem Array.sizeOf_eq {α} [SizeOf α] (cs : Array α) :
sizeOf cs = 1 + sizeOf cs.data := rfl
def T.size : T → Nat
| .mk cs => cs.attach.foldl (init := 0) fun n ⟨c, _hc⟩ => n + c.size
termination_by _ t => sizeOf t
Do I really have to tell Lean to unfold sizeOf
here?
Joachim Breitner (Oct 26 2023 at 19:32):
Ah, looks like there is setup for such recursion in https://leanprover-community.github.io/mathlib4_docs/Init/Data/Array/Mem.html, but it (needlessly) requires decidable equality on the elements, and I can’t quite get Array.sizeOf_lt_of_mem
to work here.
Joachim Breitner (Oct 26 2023 at 19:37):
This works:
inductive T : Type where
| mk : Array T -> T
opaque Array.attach {α} [DecidableEq α]: (a : Array α) → Array ({ x : α // x ∈ a })
instance : DecidableEq T := sorry
macro "array_mem_dec" : tactic =>
`(tactic| first
| apply Array.sizeOf_lt_of_mem; assumption; done
| apply Nat.lt_trans (Array.sizeOf_lt_of_mem ?h)
case' h => assumption
simp_arith)
macro_rules | `(tactic| decreasing_trivial) => `(tactic| array_mem_dec)
def T.size : T → Nat
| .mk cs => cs.attach.foldl (init := 0) fun n ⟨c, _hc⟩ => n + c.size
Is the setup in Init.Data.Array.Mem
incomplete? It defines Array.sizeOf_lt_of_mem
, but doesn’t register it with decreasing_trivial
in the same way that List.sizeOf_lt_of_mem
is set up. Maybe a simple omission because nobody complained loudly enough yet. If that’s the case, then <https://github.com/leanprover/lean4/pull/2774> should improve matters. If and once that tickles through to std4
I can also add Array.attach
there.
Last updated: Dec 20 2023 at 11:08 UTC