acc-0.1: library/Acc.hs
module Acc
(
Acc,
)
where
import Acc.Prelude
import qualified Acc.BinTree1 as BinTree1
import qualified Data.Foldable as Foldable
{-|
Data structure intended for accumulating a sequence of elements
for later traversal or folding.
Useful for implementing all kinds of builders on top.
To produce a single element 'Acc' use 'pure'.
To produce a multielement 'Acc' use 'fromList'.
To combine use '<|>' or '<>' and other 'Alternative' and 'Monoid'-related utils.
To extract elements use 'Foldable' API.
The benchmarks show that for the described use-case this data-structure
is on average 2 times faster than 'Data.DList.DList' and 'Data.Sequence.Seq',
is on par with list when you always prepend elements and
is exponentially faster than list when you append.
Internally it is implemented as a simple binary tree
with all functions optimized to use tail recursion,
ensuring that you don\'t get stack overflow.
-}
data Acc a =
EmptyAcc |
TreeAcc !(BinTree1.BinTree1 a)
deriving (Generic, Generic1)
instance NFData a => NFData (Acc a)
instance NFData1 Acc
deriving instance Functor Acc
instance Foldable Acc where
foldMap f =
\ case
TreeAcc a ->
foldMap f a
EmptyAcc ->
mempty
foldMap' f =
\ case
TreeAcc a ->
foldMap' f a
EmptyAcc ->
mempty
foldr step acc =
\ case
TreeAcc a ->
foldr step acc a
EmptyAcc ->
acc
foldr' step acc =
\ case
TreeAcc a ->
foldr' step acc a
EmptyAcc ->
acc
foldl' step acc =
\ case
TreeAcc a ->
foldl' step acc a
EmptyAcc ->
acc
sum =
foldl' (+) 0
deriving instance Traversable Acc
instance Applicative Acc where
pure =
TreeAcc . BinTree1.Leaf
(<*>) =
\ case
TreeAcc a ->
\ case
TreeAcc b ->
TreeAcc (BinTree1.ap a b)
EmptyAcc ->
EmptyAcc
EmptyAcc ->
const EmptyAcc
instance Alternative Acc where
empty =
EmptyAcc
(<|>) =
\ case
TreeAcc a ->
\ case
TreeAcc b ->
TreeAcc (BinTree1.Branch a b)
EmptyAcc ->
TreeAcc a
EmptyAcc ->
id
instance Semigroup (Acc a) where
(<>) =
(<|>)
instance Monoid (Acc a) where
mempty =
empty
instance IsList (Acc a) where
type Item (Acc a) = a
fromList =
\ case
a : b -> TreeAcc (BinTree1.fromList1 a b)
_ -> EmptyAcc
toList =
\ case
TreeAcc a ->
foldr (:) [] a
_ ->
[]
instance Show a => Show (Acc a) where
show =
show . toList