@@ -228,20 +228,31 @@ null = Bundle.null . stream
228
228
-- Indexing
229
229
-- --------
230
230
231
+ -- NOTE: [Strict indexing]
232
+ -- ~~~~~~~~~~~~~~~~~~~~~~~
233
+ --
234
+ -- Why index parameters are strict in indexing ((!), (!?)) functions
235
+ -- and functions for accessing elements in mutable arrays ('unsafeRead',
236
+ -- 'unsafeWrite', 'unsafeModify'), and slice functions?
237
+ --
238
+ -- These function call class methods ('basicUnsafeIndexM',
239
+ -- 'basicUnsafeRead', etc) and, unless (!) was already specialised to
240
+ -- a specific v, GHC has no clue that i is most certainly to be used
241
+ -- eagerly. Bang before i hints this vital for optimizer information.
242
+
243
+
231
244
infixl 9 !
232
245
-- | O(1) Indexing.
233
246
(!) :: (HasCallStack , Vector v a ) => v a -> Int -> a
234
247
{-# INLINE_FUSED (!) #-}
248
+ -- See NOTE: [Strict indexing]
235
249
(!) v ! i = checkIndex Bounds i (length v) $ unBox (basicUnsafeIndexM v i)
236
- -- Why do we need ! before i?
237
- -- The reason is that 'basicUnsafeIndexM' is a class member and, unless (!) was
238
- -- already specialised to a specific v, GHC has no clue that i is most certainly
239
- -- to be used eagerly. Bang before i hints this vital for optimizer information.
240
250
241
251
infixl 9 !?
242
252
-- | O(1) Safe indexing.
243
253
(!?) :: Vector v a => v a -> Int -> Maybe a
244
254
{-# INLINE_FUSED (!?) #-}
255
+ -- See NOTE: [Strict indexing]
245
256
-- Use basicUnsafeIndexM @Box to perform the indexing eagerly.
246
257
v !? (! i)
247
258
| i `inRange` length v = case basicUnsafeIndexM v i of Box a -> Just a
@@ -261,6 +272,7 @@ last v = v ! (length v - 1)
261
272
-- | /O(1)/ Unsafe indexing without bounds checking.
262
273
unsafeIndex :: Vector v a => v a -> Int -> a
263
274
{-# INLINE_FUSED unsafeIndex #-}
275
+ -- See NOTE: [Strict indexing]
264
276
unsafeIndex v ! i = checkIndex Unsafe i (length v) $ unBox (basicUnsafeIndexM v i)
265
277
266
278
-- | /O(1)/ First element, without checking if the vector is empty.
@@ -457,6 +469,7 @@ unsafeSlice :: Vector v a => Int -- ^ @i@ starting index
457
469
-> v a
458
470
-> v a
459
471
{-# INLINE_FUSED unsafeSlice #-}
472
+ -- See NOTE: [Strict indexing]
460
473
unsafeSlice ! i ! n v = checkSlice Unsafe i n (length v) $ basicUnsafeSlice i n v
461
474
462
475
-- | /O(1)/ Yield all but the last element without copying. The vector may not
0 commit comments