indexM-style accessor for arrays?
Pretty much everything I've seen being done with basic
Arrays says something along the lines of "You have to force the argument; otherwise, you get a thunk that holds a reference to the array". An example of that is
But it really shouldn't be this way. The
primitive and the
vector have ways of obtaining a value from an array that doesn't leave a thunk hanging around. The basic prototype is
indexArrayM :: Monad m => Array a -> Int -> m a
And having this sort of thing available for standard
Arrays would be useful because
Array is one of the first packages users see when they look for something like arrays in Haskell. Also, it's tagged
vector, and there are references to them in
containers, which is again a package lots of people use. It'd also mean that the
Traversable instances don't leak memory.
As a sort-of-related side note, we should also have a function
(!?), which functions like the similarly-named function in
vector, and has the signature
(!?) :: (IArray a e, Ix i) => a i e -> i -> Maybe e
This would, in addition to not leaving a thunk when the
Maybe is deconstructed, also eliminate a common use pattern when it comes to arrays: The user of
(!) checks the bounds of the array, does something if it's outside, then passes the index to
(!) which... checks the bounds again. Having a function which works like
Maps would be a boon here.
Having this work for all
IArrays, not just
Array, would require a new function in the
IArray typeclass, which might break existing packages that derive a new
IArray. However, the function added could be along the lines of:
unsafeAtM :: (Applicative f, Ix i) => a i e -> i -> f e unsafeAtM a i f = pure (unsafeAt a i)
which would be a default that, while it doesn't grant the benefits of using a monadic-type accessor, would ensure the code doesn't break while the packages that use/derive it are upgraded.