packages feed

antelude-0.1.0: src/Antelude/List.hs

{- |
Module      : Antelude.List
Description : Contains some functions for Lists, and reexports the Data.List module.
Maintainer  : dneavesdev@pm.me
-}
module Antelude.List
    ( -- * Rexports
      module ListExp
      -- * New and Reconstructed for safety
    , append
    , atIndex
    , combine
    , cons
    , contains
    , difference
    , head
    , init
    , last
    , prepend
    , tail
    ) where

import safe           Antelude.Function              ( (<|), (|>) )
import safe           Antelude.Internal.TypesClasses
    ( Bool
    , Eq
    , Int
    , Maybe (..)
    , Ordering (..)
    )
import safe qualified Antelude.Internal.TypesClasses as ATC ( List )

import safe           Data.List                      as ListExp hiding
    ( head
    , init
    , last
    , tail
    , (++)
    , (\\)
    )
import safe qualified Data.List                      as List

import safe           Prelude                        ( Ord (compare) )


-- | A safe implementation of 'head'. Returns 'Nothing' if if the 'List' is empty.
head :: ATC.List a -> Maybe a
head lst = case lst of
  []    -> Nothing
  [x]   -> Just x
  x : _ -> Just x


-- | A safe implementation of 'last'. Returns 'Nothing' if if the 'List' is empty.
last :: ATC.List a -> Maybe a
last lst = case List.reverse lst of
  []    -> Nothing
  [x]   -> Just x
  x : _ -> Just x


-- | A safe implementation of 'tail'. Returns 'Nothing' if if the 'List' is empty.
tail :: ATC.List a -> Maybe (ATC.List a)
tail lst = case lst of
  _ : xs -> Just xs
  _      -> Nothing


-- | A safe implementation of 'init'. Returns 'Nothing' if if the 'List' is empty.
init :: ATC.List a -> Maybe (ATC.List a)
init lst = case List.reverse lst of
  _ : xs -> Just <| List.reverse xs
  _      -> Nothing


{- |
   Obtain the element at the given index, starting at 0. 'Nothing' if the index is not valid.
-}
atIndex :: Int -> ATC.List a -> Maybe a
atIndex index lst = case compare index 0 of
  LT ->
    Nothing
  _ ->
    lst
      |> List.drop
        index
      |> head

-- | Defined as 'Data.List.elem'. See if something is a member of a list
contains :: Eq a => a -> ATC.List a -> Bool
contains = List.elem


{- |
   Defined as '(Data.List.\\)':

   The (\\\\) function is list difference (non-associative). In the result of xs \\\\ ys, the first occurrence of each element of ys in turn (if any) has been removed from xs. Thus (xs <> ys) \\\\ xs == ys.
-}
difference :: (Eq a) => ATC.List a -> ATC.List a -> ATC.List a
difference = (List.\\)


-- | Defined as '(Data.List.++)'. You could use (Antelude.<>) instead.
combine :: ATC.List a -> ATC.List a -> ATC.List a
combine = (List.++)


-- | Add an item to the end of a 'List'.
append :: a -> ATC.List a -> ATC.List a
append new lst = combine lst [new]


-- | Add an item to the beginning of a 'List'.
prepend :: a -> ATC.List a -> ATC.List a
prepend new lst = new : lst


-- | Defined as 'prepend'. Add an item to the beginning of a 'List'.
cons :: a -> ATC.List a -> ATC.List a
cons = prepend