diff options
-rw-r--r-- | libraries/base/Data/List.hs | 1 | ||||
-rw-r--r-- | libraries/base/Data/OldList.hs | 1 | ||||
-rw-r--r-- | libraries/base/GHC/List.hs | 35 | ||||
-rw-r--r-- | libraries/base/changelog.md | 2 |
4 files changed, 34 insertions, 5 deletions
diff --git a/libraries/base/Data/List.hs b/libraries/base/Data/List.hs index d7a5922031..a81c743357 100644 --- a/libraries/base/Data/List.hs +++ b/libraries/base/Data/List.hs @@ -127,6 +127,7 @@ module Data.List -- | These functions treat a list @xs@ as a indexed collection, -- with indices ranging from 0 to @'length' xs - 1@. + , (!?) , (!!) , elemIndex diff --git a/libraries/base/Data/OldList.hs b/libraries/base/Data/OldList.hs index 176c72547c..8e610ebba0 100644 --- a/libraries/base/Data/OldList.hs +++ b/libraries/base/Data/OldList.hs @@ -127,6 +127,7 @@ module Data.OldList -- | These functions treat a list @xs@ as a indexed collection, -- with indices ranging from 0 to @'length' xs - 1@. + , (!?) , (!!) , elemIndex diff --git a/libraries/base/GHC/List.hs b/libraries/base/GHC/List.hs index 658dabe302..4427d1af1b 100644 --- a/libraries/base/GHC/List.hs +++ b/libraries/base/GHC/List.hs @@ -31,7 +31,7 @@ module GHC.List ( -- Other functions foldl1', concat, concatMap, map, (++), filter, lookup, - head, last, tail, init, uncons, (!!), + head, last, tail, init, uncons, (!?), (!!), scanl, scanl1, scanl', scanr, scanr1, iterate, iterate', repeat, replicate, cycle, take, drop, splitAt, takeWhile, dropWhile, span, break, reverse, @@ -49,7 +49,7 @@ import GHC.Num (Num(..)) import GHC.Num.Integer (Integer) import GHC.Stack.Types (HasCallStack) -infixl 9 !! +infixl 9 !?, !! infix 4 `elem`, `notElem` -- $setup @@ -1370,9 +1370,10 @@ concat = foldr (++) [] -- >>> ['a', 'b', 'c'] !! (-1) -- *** Exception: Prelude.!!: negative index -- --- WARNING: This function is partial. You can use --- <https://hackage.haskell.org/package/safe/docs/Safe.html#v:atMay atMay> --- instead. +-- WARNING: This function is partial, and should only be used if you are +-- sure that the indexing will not fail. Otherwise, use 'Data.List.!?'. +-- +-- WARNING: This function takes linear time in the index. #if defined(USE_REPORT_PRELUDE) (!!) :: [a] -> Int -> a xs !! n | n < 0 = errorWithoutStackTrace "Prelude.!!: negative index" @@ -1401,6 +1402,30 @@ xs !! n _ -> r (k-1)) tooLarge xs n #endif +-- | List index (subscript) operator, starting from 0. Returns 'Nothing' +-- if the index is out of bounds +-- +-- >>> ['a', 'b', 'c'] !? 0 +-- Just 'a' +-- >>> ['a', 'b', 'c'] !? 2 +-- Just 'c' +-- >>> ['a', 'b', 'c'] !? 3 +-- Nothing +-- >>> ['a', 'b', 'c'] !? (-1) +-- Nothing +-- +-- This is the total variant of the partial '!!' operator. +-- +-- WARNING: This function takes linear time in the index. +(!?) :: [a] -> Int -> Maybe a + +{-# INLINABLE (!?) #-} +xs !? n + | n < 0 = Nothing + | otherwise = foldr (\x r k -> case k of + 0 -> Just x + _ -> r (k-1)) (const Nothing) xs n + -------------------------------------------------------------- -- The zip family -------------------------------------------------------------- diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md index 01dd9fe894..51c02c788f 100644 --- a/libraries/base/changelog.md +++ b/libraries/base/changelog.md @@ -58,6 +58,8 @@ freeing a `Pool`. (#14762) (#18338) * `Type.Reflection.Unsafe` is now marked as unsafe. * Add `Data.Typeable.heqT`, a kind-heterogeneous version of `Data.Typeable.eqT`. + * Add `Data.List.!?` per + [CLC proposal #110](https://github.com/haskell/core-libraries-committee/issues/110). ## 4.17.0.0 *August 2022* |