content: {-# LANGUAGE Safe #-}
  
  -- | This module contains safe functions to work with list type (mostly with 'NonEmpty').
  
  module Universum.List.Safe
         ( uncons
         , whenNotNull
         , whenNotNullM
         , foldr1
         , foldl1
         , minimum
         , maximum
         , minimumBy
         , maximumBy
         ) where
  
  import qualified Data.Foldable as F
  import Data.Ord (Ord, Ordering)
  
  import Universum.Applicative (Applicative, pass)
  import Universum.List.Reexport (NonEmpty (..))
  import Universum.Monad (Maybe (..), Monad (..))
  
  -- $setup
  -- >>> import Universum.Applicative (pure)
  -- >>> import Universum.Base ((==), (+), even)
  -- >>> import Universum.Bool (Bool (..), not)
  -- >>> import Universum.Container (length)
  -- >>> import Universum.Function (($))
  -- >>> import Universum.Print (print)
  
  -- | Destructuring list into its head and tail if possible. This function is total.
  --
  -- >>> uncons []
  -- Nothing
  -- >>> uncons [1..5]
  -- Just (1,[2,3,4,5])
  -- >>> uncons (5 : [1..5]) >>= \(f, l) -> pure $ f == length l
  -- Just True
  uncons :: [a] -> Maybe (a, [a])
  uncons []     = Nothing
  uncons (x:xs) = Just (x, xs)
  
  {- | Performs given action over 'NonEmpty' list if given list is non empty.
  
  >>> whenNotNull [] $ \(b :| _) -> print (not b)
  >>> whenNotNull [False,True] $ \(b :| _) -> print (not b)
  True
  
  -}
  whenNotNull :: Applicative f => [a] -> (NonEmpty a -> f ()) -> f ()
  whenNotNull []     _ = pass
  whenNotNull (x:xs) f = f (x :| xs)
  {-# INLINE whenNotNull #-}
  
  -- | Monadic version of 'whenNotNull'.
  whenNotNullM :: Monad m => m [a] -> (NonEmpty a -> m ()) -> m ()
  whenNotNullM ml f = ml >>= \l -> whenNotNull l f
  {-# INLINE whenNotNullM #-}
  
  -- | A variant of 'foldl' that has no base case, and thus may only be
  -- applied to 'NonEmpty'.
  --
  -- >>> foldl1 (+) (1 :| [2,3,4,5])
  -- 15
  foldl1 :: (a -> a -> a) -> NonEmpty a -> a
  foldl1 = F.foldl1
  {-# INLINE foldl1 #-}
  
  -- | A variant of 'foldr' that has no base case, and thus may only be
  -- applied to 'NonEmpty'.
  --
  -- >>> foldr1 (+) (1 :| [2,3,4,5])
  -- 15
  foldr1 :: (a -> a -> a) -> NonEmpty a -> a
  foldr1 = F.foldr1
  {-# INLINE foldr1 #-}
  
  -- | The least element of a 'NonEmpty' with respect to the given
  -- comparison function.
  minimumBy :: (a -> a -> Ordering) -> NonEmpty a -> a
  minimumBy = F.minimumBy
  {-# INLINE minimumBy #-}
  
  -- | The least element of a 'NonEmpty'.
  --
  -- >>> minimum (1 :| [2,3,4,5])
  -- 1
  minimum :: Ord a => NonEmpty a -> a
  minimum = F.minimum
  {-# INLINE minimum #-}
  
  -- | The largest element of a 'NonEmpty' with respect to the given
  -- comparison function.
  maximumBy :: (a -> a -> Ordering) -> NonEmpty a -> a
  maximumBy = F.maximumBy
  {-# INLINE maximumBy #-}
  
  -- | The largest element of a 'NonEmpty'.
  --
  -- >>> maximum (1 :| [2,3,4,5])
  -- 5
  maximum :: Ord a => NonEmpty a -> a
  maximum = F.maximum
  {-# INLINE maximum #-}
  