{-# LANGUAGE CPP #-}
module Basement.Compat.ExtList
    ( length
    , null
    , sum
    , reverse
    , (!!)
    ) where

import Basement.Compat.Base
import Basement.Numerical.Additive
import Basement.Types.OffsetSize
import qualified GHC.List as List

-- | Compute the size of the list
length :: [a] -> CountOf a
#if MIN_VERSION_base(4,8,0)
length :: [a] -> CountOf a
length = Int -> CountOf a
forall ty. Int -> CountOf ty
CountOf (Int -> CountOf a) -> ([a] -> Int) -> [a] -> CountOf a
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Int -> a -> Int) -> Int -> [a] -> Int
forall a b. (b -> a -> b) -> b -> [a] -> b
List.foldl' (\c :: Int
c _ -> Int
cInt -> Int -> Int
forall a. Additive a => a -> a -> a
+1) 0
#else
length = CountOf . loop 0
  where loop !acc []     = acc
        loop !acc (_:xs) = loop (1+acc) xs
#endif

null :: [a] -> Bool
null :: [a] -> Bool
null []    = Bool
True
null (_:_) = Bool
False

-- | Sum the element in a list
sum :: Additive n => [n] -> n
sum :: [n] -> n
sum []     = n
forall a. Additive a => a
azero
sum (i :: n
i:is :: [n]
is) = n -> [n] -> n
forall t. Additive t => t -> [t] -> t
loop n
i [n]
is
  where
    loop :: t -> [t] -> t
loop !t
acc [] = t
acc
    loop !t
acc (x :: t
x:xs :: [t]
xs) = t -> [t] -> t
loop (t
acct -> t -> t
forall a. Additive a => a -> a -> a
+t
x) [t]
xs
    {-# INLINE loop #-}

reverse :: [a] -> [a]
reverse :: [a] -> [a]
reverse l :: [a]
l =  [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
go [a]
l []
  where
    go :: [a] -> [a] -> [a]
go []     acc :: [a]
acc = [a]
acc
    go (x :: a
x:xs :: [a]
xs) acc :: [a]
acc = [a] -> [a] -> [a]
go [a]
xs (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
acc)

(!!) :: [a] -> Offset a -> a
[]    !! :: [a] -> Offset a -> a
!! _  = [Char] -> a
forall a. HasCallStack => [Char] -> a
error "invalid offset for !!"
(x :: a
x:_) !! 0  = a
x
(_:xs :: [a]
xs) !! i :: Offset a
i = [a]
xs [a] -> Offset a -> a
forall a. [a] -> Offset a -> a
!! Offset a -> Offset a
forall a. Enum a => a -> a
pred Offset a
i