{-# LANGUAGE Safe #-} {- | Module : Relude.List Copyright : (c) 2016 Stephen Diehl (c) 2016-2018 Serokell (c) 2018-2023 Kowainik SPDX-License-Identifier : MIT Maintainer : Kowainik <xrom.xkov@gmail.com> Stability : Stable Portability : Portable Utility functions to work with lists and 'NonEmpty' lists. -} module Relude.List ( module Relude.List.Reexport -- $reexport , module Relude.List.NonEmpty -- $nonempty , (!!?) , maybeAt , partitionWith ) where import Relude.Base ((<)) import Relude.Bool (otherwise) import Relude.Function (flip, (.)) import Relude.List.NonEmpty import Relude.List.Reexport import Relude.Monad (Either, Maybe (..), partitionEithers) import Relude.Numeric (Int, (-)) -- $setup -- >>> import Relude {- | Safer version of 'Relude.Unsafe.!!', returns a Maybe. Get element from list using index value starting from `0`. >>> [] !!? 0 Nothing >>> ["a", "b", "c"] !!? 3 Nothing >>> [1, 2, 3] !!? (-1) Nothing >>> ["a", "b", "c"] !!? 2 Just "c" @since 0.6.0.0 -} infix 9 !!? (!!?) :: [a] -> Int -> Maybe a !!? :: forall a. [a] -> Int -> Maybe a (!!?) [a] xs Int i | Int i Int -> Int -> Bool forall a. Ord a => a -> a -> Bool < Int 0 = Maybe a forall a. Maybe a Nothing | Bool otherwise = Int -> [a] -> Maybe a forall a. Int -> [a] -> Maybe a go Int i [a] xs where go :: Int -> [a] -> Maybe a go :: forall a. Int -> [a] -> Maybe a go Int 0 (a x:[a] _) = a -> Maybe a forall a. a -> Maybe a Just a x go Int j (a _:[a] ys) = Int -> [a] -> Maybe a forall a. Int -> [a] -> Maybe a go (Int j Int -> Int -> Int forall a. Num a => a -> a -> a - Int 1) [a] ys go Int _ [] = Maybe a forall a. Maybe a Nothing {-# INLINE (!!?) #-} {- | '!!?' with its arguments flipped. Get element from list using index value starting from `0`. >>> maybeAt 0 [] Nothing >>> maybeAt 3 ["a", "b", "c"] Nothing >>> maybeAt (-1) [1, 2, 3] Nothing >>> maybeAt 2 ["a", "b", "c"] Just "c" @since 1.0.0.0 -} maybeAt :: Int -> [a] -> Maybe a maybeAt :: forall a. Int -> [a] -> Maybe a maybeAt = ([a] -> Int -> Maybe a) -> Int -> [a] -> Maybe a forall a b c. (a -> b -> c) -> b -> a -> c flip [a] -> Int -> Maybe a forall a. [a] -> Int -> Maybe a (!!?) {-# INLINE maybeAt #-} {- | Partitions a list based on the result of function which produces an Either value. List of all elements producing Left are extracted, in order, to the first element of the output tuple. Similarly, a list of all elements producing Right are extracted to the second element of output. >>> :{ divideEvenOrShow :: Int -> Either Int String divideEvenOrShow n | even n = Left $ n `div` 2 | otherwise = Right $ "Odd: " <> show n :} >>> partitionWith divideEvenOrShow [1 .. 6] ([1,2,3],["Odd: 1","Odd: 3","Odd: 5"]) @since 1.0.0.0 -} partitionWith :: (a -> Either b c) -> [a] -> ([b], [c]) partitionWith :: forall a b c. (a -> Either b c) -> [a] -> ([b], [c]) partitionWith a -> Either b c f = [Either b c] -> ([b], [c]) forall a b. [Either a b] -> ([a], [b]) partitionEithers ([Either b c] -> ([b], [c])) -> ([a] -> [Either b c]) -> [a] -> ([b], [c]) forall b c a. (b -> c) -> (a -> b) -> a -> c . (a -> Either b c) -> [a] -> [Either b c] forall a b. (a -> b) -> [a] -> [b] map a -> Either b c f {-# INLINE partitionWith #-} {- $reexport Most of the "Data.List" types and function. Note, that list partial functions (e.g. 'Data.List.head') are not exported from "Data.List". Instead @relude@ provides safe functions that work with 'Data.List.NonEmpty.NonEmpty'. You can find them in the "Relude.List.NonEmpty" module instead. -} {- $nonempty Reexports from "Data.List.NonEmpty" and additional safe functions to work with list type in terms of 'NonEmpty'. -}