    {-# 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 = Int -> CountOf a
    forall ty. Int -> CountOf ty
    CountOf (Int -> CountOf a) -> ([a] -> Int) -> [a] -> CountOf a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    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' (\Int
    c a
    _ -> Int
    cInt -> Int -> Int
    forall 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 []     = n
    forall a. Additive a => a
    azero
    sum (n
    i:[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 (t
    x:[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 :: forall a. [a] -> [a]
    reverse [a]
    l =  [a] -> [a] -> [a]
    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
    xa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    acc)

    (!!) :: [a] -> Offset a -> a
    []    !! :: forall a. [a] -> Offset a -> a
    !! Offset a
    _  = [Char] -> 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 [a] -> Offset a -> a
    forall a. [a] -> Offset a -> a
    !! Offset a -> Offset a
    forall a. Enum a => a -> a
    pred Offset a
    i