indexM or (!?)-style accessor for arrays?

Zemyla zemyla at gmail.com
Tue Aug 13 16:24:09 UTC 2019


This is an issue I originally proposed on GHC Trac, but I'm posting it
here because (I think) the Data.Array package is under the purview of
the Libraries committee.

The vector package has indexM and its cousins so that a user can be
strict in the array without necessarily being strict in the value
retrieved from that array. Arrays don't have that sort of thing,
meaning that anything you do that takes an array will necessarily
leave references to the array unless you force the whole thing, and
that's not only inefficient, it's untenable for general libraries.

What I'm thinking is that the IArray class should have a function like

unsafeAtM :: (Array a e, Ix i, Applicative m) => a i e -> Int -> m e

For compatibility with older code that wouldn't necessarily define
this but would define unsafeAt, we'd have the default implementation

unsafeAtM a !n = pure (unsafeAt a n)

Also, you could have unsafeAt defined in terms of unsafeAtM, so the
minimal implementation could require only one of them:

unsafeAt = (coerce :: (a i e -> Int -> Identity e) -> a i e -> Int ->
e) unsafeAtM

Also, (!?) would be a "safe" indexing tool for arrays, which would
incidentally also force the array without forcing the value inside.
You would have

(!?) :: (Array a e, Ix i) => a i e -> i -> Maybe e
(!?) a e = case bounds a of
  p@(l, u) -> case inRange p e of
    True -> unsafeAtM arr $ unsafeIndex p e
    False -> Nothing


More information about the Libraries mailing list