{-# 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 :: forall a. [a] -> CountOf a
length = forall ty. Int -> CountOf ty
CountOf forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (b -> a -> b) -> b -> [a] -> b
List.foldl' (\Int
c a
_ -> Int
cforall a. Additive a => a -> a -> a
+Int
1) Int
0
#else
length = CountOf . loop 0
  where loop !acc []     = acc
        loop !acc (_:xs) = loop (1+acc) xs
#endif

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

-- | Sum the element in a list
sum :: Additive n => [n] -> n
sum :: forall n. Additive n => [n] -> n
sum []     = forall a. Additive a => a
azero
sum (n
i:[n]
is) = 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 (t
x:[t]
xs) = t -> [t] -> t
loop (t
accforall a. Additive a => a -> a -> a
+t
x) [t]
xs
    {-# INLINE loop #-}

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

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