@@ -228,19 +228,35 @@ 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 (!) #-}
235
- (!) v i = checkIndex Bounds i (length v) $ unBox (basicUnsafeIndexM v i)
248
+ -- See NOTE: [Strict indexing]
249
+ (!) v ! i = checkIndex Bounds i (length v) $ unBox (basicUnsafeIndexM v i)
236
250
237
251
infixl 9 !?
238
252
-- | O(1) Safe indexing.
239
253
(!?) :: Vector v a => v a -> Int -> Maybe a
240
254
{-# INLINE_FUSED (!?) #-}
255
+ -- See NOTE: [Strict indexing]
241
256
-- Use basicUnsafeIndexM @Box to perform the indexing eagerly.
242
- v !? i | i `inRange` length v = case basicUnsafeIndexM v i of Box a -> Just a
243
- | otherwise = Nothing
257
+ v !? (! i)
258
+ | i `inRange` length v = case basicUnsafeIndexM v i of Box a -> Just a
259
+ | otherwise = Nothing
244
260
245
261
246
262
-- | /O(1)/ First element.
@@ -256,7 +272,8 @@ last v = v ! (length v - 1)
256
272
-- | /O(1)/ Unsafe indexing without bounds checking.
257
273
unsafeIndex :: Vector v a => v a -> Int -> a
258
274
{-# INLINE_FUSED unsafeIndex #-}
259
- unsafeIndex v i = checkIndex Unsafe i (length v) $ unBox (basicUnsafeIndexM v i)
275
+ -- See NOTE: [Strict indexing]
276
+ unsafeIndex v ! i = checkIndex Unsafe i (length v) $ unBox (basicUnsafeIndexM v i)
260
277
261
278
-- | /O(1)/ First element, without checking if the vector is empty.
262
279
unsafeHead :: Vector v a => v a -> a
@@ -316,7 +333,7 @@ unsafeLast v = unsafeIndex v (length v - 1)
316
333
-- element) is evaluated eagerly.
317
334
indexM :: (HasCallStack , Vector v a , Monad m ) => v a -> Int -> m a
318
335
{-# INLINE_FUSED indexM #-}
319
- indexM v i = checkIndex Bounds i (length v) $ liftBox $ basicUnsafeIndexM v i
336
+ indexM v ! i = checkIndex Bounds i (length v) $ liftBox $ basicUnsafeIndexM v i
320
337
321
338
-- | /O(1)/ First element of a vector in a monad. See 'indexM' for an
322
339
-- explanation of why this is useful.
@@ -334,7 +351,7 @@ lastM v = indexM v (length v - 1)
334
351
-- explanation of why this is useful.
335
352
unsafeIndexM :: (Vector v a , Monad m ) => v a -> Int -> m a
336
353
{-# INLINE_FUSED unsafeIndexM #-}
337
- unsafeIndexM v i = checkIndex Unsafe i (length v)
354
+ unsafeIndexM v ! i = checkIndex Unsafe i (length v)
338
355
$ liftBox
339
356
$ basicUnsafeIndexM v i
340
357
@@ -452,7 +469,8 @@ unsafeSlice :: Vector v a => Int -- ^ @i@ starting index
452
469
-> v a
453
470
-> v a
454
471
{-# INLINE_FUSED unsafeSlice #-}
455
- unsafeSlice i n v = checkSlice Unsafe i n (length v) $ basicUnsafeSlice i n v
472
+ -- See NOTE: [Strict indexing]
473
+ unsafeSlice ! i ! n v = checkSlice Unsafe i n (length v) $ basicUnsafeSlice i n v
456
474
457
475
-- | /O(1)/ Yield all but the last element without copying. The vector may not
458
476
-- be empty, but this is not checked.
@@ -993,7 +1011,7 @@ backpermute v is = seq v
993
1011
-- NOTE: we do it this way to avoid triggering LiberateCase on n in
994
1012
-- polymorphic code
995
1013
index :: HasCallStack => Int -> Box a
996
- index i = checkIndex Bounds i n $ basicUnsafeIndexM v i
1014
+ index ! i = checkIndex Bounds i n $ basicUnsafeIndexM v i
997
1015
998
1016
-- | Same as 'backpermute', but without bounds checking.
999
1017
unsafeBackpermute :: (Vector v a , Vector v Int ) => v a -> v Int -> v a
@@ -1010,7 +1028,7 @@ unsafeBackpermute v is = seq v
1010
1028
{-# INLINE index #-}
1011
1029
-- NOTE: we do it this way to avoid triggering LiberateCase on n in
1012
1030
-- polymorphic code
1013
- index i = checkIndex Unsafe i n $ basicUnsafeIndexM v i
1031
+ index ! i = checkIndex Unsafe i n $ basicUnsafeIndexM v i
1014
1032
1015
1033
-- Safe destructive updates
1016
1034
-- ------------------------
@@ -2534,7 +2552,7 @@ streamR v = v `seq` n `seq` (Bundle.unfoldr get n `Bundle.sized` Exact n)
2534
2552
2535
2553
{-# INLINE get #-}
2536
2554
get 0 = Nothing
2537
- get i = let i' = i- 1
2555
+ get i = let ! i' = i- 1
2538
2556
in
2539
2557
case basicUnsafeIndexM v i' of Box x -> Just (x, i')
2540
2558
0 commit comments