1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
module VectorBuilder.Core.Builder where
import qualified Data.Vector.Generic as B
import qualified VectorBuilder.Core.Update as A
import VectorBuilder.Prelude hiding (concat, empty)
-- |
-- An abstraction over the size of a vector for the process of its construction.
--
-- It postpones the actual construction of a vector until the execution of the builder.
data Builder element
= Builder !Int !(A.Update element)
-- |
-- Gets the size of a Builder.
{-# INLINE size #-}
size :: Builder element -> Int
size (Builder s _) = s
-- * Initialisation
-- |
-- Empty builder.
{-# INLINE empty #-}
empty :: Builder element
empty =
Builder 0 A.empty
-- |
-- Builder of a single element.
{-# INLINE singleton #-}
singleton :: element -> Builder element
singleton element =
Builder 1 (A.write element)
-- |
-- Builder from an immutable vector of elements.
--
-- Supports all kinds of vectors: boxed, unboxed, primitive, storable.
{-# INLINE vector #-}
vector :: (B.Vector vector element) => vector element -> Builder element
vector vector =
Builder (B.length vector) (A.writeMany vector)
{-# INLINE foldable #-}
foldable :: (Foldable foldable) => foldable element -> Builder element
foldable foldable =
Builder (length foldable) (A.writeFoldable foldable)
-- * Updates
{-# INLINE snoc #-}
snoc :: element -> Builder element -> Builder element
snoc element (Builder size update) =
Builder (succ size) (A.prepend size update (A.write element))
{-# INLINE cons #-}
cons :: element -> Builder element -> Builder element
cons element (Builder size update) =
Builder (succ size) (A.prepend 1 (A.write element) update)
{-# INLINE prepend #-}
prepend :: Builder element -> Builder element -> Builder element
prepend (Builder leftSize leftUpdate) (Builder rightSize rightUpdate) =
Builder (leftSize + rightSize) (A.prepend leftSize leftUpdate rightUpdate)
{-# INLINE append #-}
append :: Builder element -> Builder element -> Builder element
append =
flip prepend
{-# INLINE concat #-}
concat :: (Foldable foldable) => foldable (Builder element) -> Builder element
concat builders =
Builder
( let step size (Builder builderSize _) = size + builderSize
in foldl' step 0 builders
)
( A.Update
( \mVector offset ->
foldM_
( \index (Builder size (A.Update st)) ->
st mVector index $> index + size
)
offset
builders
)
)
-- * Instances
-- |
-- Provides support for /O(1)/ concatenation.
instance Semigroup (Builder element) where
{-# INLINE (<>) #-}
(<>) =
prepend
sconcat =
concat
-- |
-- Provides support for /O(1)/ concatenation.
instance Monoid (Builder element) where
{-# INLINE mempty #-}
mempty =
empty
{-# INLINE mappend #-}
mappend =
(<>)
{-# INLINE mconcat #-}
mconcat =
concat
|