File: Builder.hs

package info (click to toggle)
haskell-vector-builder 0.3.8.6-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 84 kB
  • sloc: haskell: 364; makefile: 3
file content (112 lines) | stat: -rw-r--r-- 2,861 bytes parent folder | download | duplicates (2)
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