content: {-# 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
  (!!?) xs i
      | i < 0     = Nothing
      | otherwise = go i xs
    where
      go :: Int -> [a] -> Maybe a
      go 0 (x:_)  = Just x
      go j (_:ys) = go (j - 1) ys
      go _ []     = 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 = flip (!!?)
  {-# 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 f = partitionEithers . map 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'.
  -}
  