Zulip Chat Archive

Stream: batteries

Topic: PR #1107 help needed with Satisfies


Shreyas Srinivas (Jan 31 2025 at 15:10):

Hello all, I need some help with working around this SatisfiesM predicate in batteries#1107

This PR is about adding some missing monadic defs for vectors (see the discussion in batteries#925). I am trying to extract the size guarantee of Array.size_modifyM (which uses Satisfies) to give me a proof that the size of the modified vector remains unchanged (around line 31). Conceptually I understand where my "proof" is going wrong. But I am not sure I know how to work around it.

Shreyas Srinivas (Jan 31 2025 at 16:27):

Update

On discord, we discussed using an [implemented_by] unsafe def ... with an unsafe cast on Array.modifyM to get a vector, and writing the safe version without using Array` defs. User Rob_23oba (who is not on Zulip) suggested something as follows:

@[inline]
unsafe def modifyMUnsafe [Monad m] (v : Vector α n) (i : Nat) (f : α  m α) : m (Vector α n) :=
  -- Array and Vector have the same internal representation, so this cast is valid
  unsafeCast (Array.modifyM v.toArray i f)

/--
`modifyM v i f` applies a monadic transformation `f` to `v[i]`
-/
@[implemented_by modifyMUnsafe]
def modifyM [Monad m] (v : Vector α n) (i : Nat) (f : α  m α) : m (Vector α n) := do
  if h : i < n then
    let x   := v[i]
    let x  f x
    pure <| v.set i x
  else
    pure v

Shreyas Srinivas (Jan 31 2025 at 16:28):

The disadvantage is that of course one is always using the unsafe version for computations in practice.

Shreyas Srinivas (Jan 31 2025 at 16:29):

The advantage is that one doesn't need extra typeclass instances like LawfulMonad, LawfulFunctor and MonadSatisfying to use satisfying

Shreyas Srinivas (Jan 31 2025 at 16:30):

What is the community's opinion on this? CC : @Kim Morrison

Kim Morrison (Jan 31 2025 at 20:39):

No unsafe definitions here please, unless there are significant performance gains which are otherwise in inaccessible. In particular, not for the sake of proofs.

Kim Morrison (Jan 31 2025 at 20:43):

Why do you want the implemented_by here in the first place?

Kim Morrison (Jan 31 2025 at 20:44):

Note that for Array/Vector I'll soon be changing the signature, so modify takes an in-bounds proof and modifyIfInBounds preserves the current behaviour parallel to List.

Shreyas Srinivas (Jan 31 2025 at 20:45):

It was an idea to get around the challenge I described above. I need to show that the size of the vector after modifyM is n and I have very little experience with SatisfiesM

Shreyas Srinivas (Jan 31 2025 at 20:47):

So to use the satisfying function to extract the proof from Array.size_modifyM, I had to add a bunch of instances and the proof is still wrong. I can see why it is wrong, but not the fix.

Kim Morrison (Jan 31 2025 at 20:47):

What's wrong with the safe definition above? Just remove the implemented by.

Shreyas Srinivas (Jan 31 2025 at 20:48):

It might not be efficient. Last time I wrote my own defs for Vector I was told that it must use the array functions.

Shreyas Srinivas (Jan 31 2025 at 20:50):

To make sure the functions use FBIP


Last updated: May 02 2025 at 03:31 UTC