packages feed

hegg-0.2.0.0: src/Data/Equality/Utils/SizedList.hs

{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE TypeFamilies #-}
{-|
   Util: A list with a O(1) size function
 -}
module Data.Equality.Utils.SizedList where

import qualified Data.List
import GHC.Exts
import Data.Foldable

-- | A list with O(1) size access and O(1) conversion to normal list
data SList a = SList ![a] {-# UNPACK #-} !Int
  deriving Traversable

instance Semigroup (SList a) where
  (<>) (SList a i) (SList b j) = SList (a <> b) (i+j)
  {-# INLINE (<>) #-}

instance Monoid (SList a) where
  mempty = SList mempty 0
  {-# INLINE mempty #-}

instance Functor SList where
  fmap f (SList a i) = SList (fmap f a) i
  {-# INLINE fmap #-}

instance Foldable SList where
  fold       ( SList l _) = fold l
  foldMap f  ( SList l _) = foldMap f l
  foldMap' f ( SList l _) = foldMap' f l
  foldr f b  ( SList l _) = foldr f b l
  foldr' f b ( SList l _) = foldr' f b l
  foldl f b  ( SList l _) = foldl f b l
  foldl' f b ( SList l _) = foldl' f b l
  foldr1 f   ( SList l _) = foldr1 f l
  foldl1 f   ( SList l _) = foldl1 f l
  toList     ( SList l _) = l
  null       ( SList l _) = Data.List.null l
  length     ( SList _ i) = i
  elem x     ( SList l _) = x `elem` l
  maximum    ( SList l _) = maximum l
  minimum    ( SList l _) = minimum l
  sum        ( SList l _) = sum l
  product    ( SList l _) = product l

instance IsList (SList a) where
  type Item (SList a) = a
  fromList l          = SList l (length l)
  fromListN i l       = SList l i
  toList (SList l _)  = l

-- | Prepend an item to the list in O(1)
(|:) :: a -> SList a -> SList a
(|:) a (SList l i) = SList (a:l) (i+1)
{-# INLINE (|:) #-}

-- | Make a normal list from the sized list in O(1)
toListSL :: SList a -> [a]
toListSL (SList l _) = l
{-# INLINE toListSL #-}

-- | Get the size of the list in O(1)
sizeSL :: SList a -> Int
sizeSL (SList _ i) = i
{-# INLINE sizeSL #-}