Skip to content

Folds over mutable vectors #326

Description

@andrewthad

I noticed a reoccurring help function across several applications that I've written, and I think it would be nice to have these in vector itself:

traverse_ ::
     (a -> m b)
  -> MVector (PrimState m) a
  -> m ()

foldM :: -- Should probably be named foldlM instead as in Data.Foldable, but vector uses foldM elsewhere
     (b -> a -> m b)
  -> b
  -> MVector (PrimState m) a
  -> m b

The implementations are both straightforward, and I'm happy to implement this if others find it worthwhile. There is the possibility of a traverse that either (a) mutates the vector in-place or (b) creates a new mutable vector. There's more room to disagree there, so if anyone is interested in that, I think that discussing it on a separate issue would be better.

Activity

  1. lehins commented on Jul 20, 2020

    @lehins
    Contributor

    I am definitely in favor of all or some these:

    • mapM_ and forM_ instead of traverse_, since the latter name would not be consistent with the pure versions
    • imapM_ and iforM_
    • foldlM_ and foldrM_
    • ifoldlM_ and ifoldrM_

    With respect to traverse that does mutation, I think I'd vote for a version that mutates the same vector in place. This of course would make the mapping function to produce elements of the same type:

    traverse ::
         (a -> m a)
      -> MVector (PrimState m) a
      -> m ()

    Which means it would be slightly different from traverse, as such maybe we should come up with a good new name for such function.

    A version that creates a new vector isn't as useful, since you can already just as easily achieve it with: unsafeFreeze >=> mapM f >=> unsafeThaw. I think there are rewrite rules that will ensure that mapM will get specialized to PrimMonad making it efficient. But, as you said we can discuss this part more in a separate ticket.

  2. leftaroundabout commented on Jul 21, 2020

    @leftaroundabout
    Contributor

    Agree with the mutable traversal. This should probably be called something like modifyTraverse or traverseModify.

    Incidentally, maybe it would also make sense to have

    modifyM :: MVector (PrimState m) a -> (a -> m a) -> Int -> m ()
    modifyAll :: MVector (PrimState m) a -> (a -> a) -> m ()
    

    And then, by extrapolation, the traversal would be called

    modifyAllM :: MVector (PrimState m) a -> (a -> m a) -> m ()
    
  3. Shimuuar commented on Jul 21, 2020

    @Shimuuar
    Contributor

    +1. We have several issues asking to extend API for mutable vectors

  4. Shimuuar commented on Oct 21, 2020

    @Shimuuar
    Contributor

    Closed in favor of #334

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions