on master help sign in
Improved documentation for builders
a0f0523Johan Tibell
Data/Text/Lazy/Builder.hs+37−24
@@ -10,7 +10,20 @@
10-- Stability : experimental
10-- Stability : experimental
11-- Portability : portable to Hugs and GHC
11-- Portability : portable to Hugs and GHC
12--
12--
13−-- Efficient construction of lazy texts.
13+-- Efficient construction of lazy @Text@ values. The principal
14+-- operations on a @Builder@ are @singleton@, @fromText@, and
15+-- @fromLazyText@, which construct new builders, and 'mappend', which
16+-- concatenates two builders.
17+--
18+-- To get maximum performance when building lazy @Text@ values using a builder, associate @mappend@ calls to the right. For example, prefer
19+--
20+-- > singleton 'a' `mappend` (singleton 'b' `mappend` singleton 'c')
21+--
22+-- to
23+--
24+-- > singleton 'a' `mappend` singleton 'b' `mappend` singleton 'c'
25+--
26+-- as the latter associates @mappend@ to the left.
14--
27--
15-----------------------------------------------------------------------------
28-----------------------------------------------------------------------------
16
29
@@ -46,15 +59,15 @@ import qualified Data.Text.Lazy as L
46
59
47------------------------------------------------------------------------
60------------------------------------------------------------------------
48
61
49−-- | A 'Builder' is an efficient way to build lazy 'L.Text's. There
62+-- | A @Builder@ is an efficient way to build lazy @Text@ values.
50−-- are several functions for constructing 'Builder's, but only one to
63+-- There are several functions for constructing builders, but only one
51−-- inspect them: to extract any data, you have to turn them into lazy
64+-- to inspect them: to extract any data, you have to turn them into
52−-- 'L.Text's using 'toLazyText'.
65+-- lazy @Text@ values using @toLazyText@.
53--
66--
54−-- Internally, a 'Builder' constructs a lazy 'L.Text' by filling byte
67+-- Internally, a builder constructs a lazy @Text@ by filling arrays
55−-- arrays piece by piece. As each buffer is filled, it is \'popped\'
68+-- piece by piece. As each buffer is filled, it is \'popped\' off, to
56−-- off, to become a new chunk of the resulting lazy 'L.Text'. All
69+-- become a new chunk of the resulting lazy @Text@. All this is
57−-- this is hidden from the user of the 'Builder'.
70+-- hidden from the user of the @Builder@.
58newtype Builder = Builder {
71newtype Builder = Builder {
59 -- Invariant (from Data.Text.Lazy):
72 -- Invariant (from Data.Text.Lazy):
60 -- The lists include no null Texts.
73 -- The lists include no null Texts.
@@ -78,7 +91,7 @@ instance Show Builder where
78
91
79------------------------------------------------------------------------
92------------------------------------------------------------------------
80
93
81−-- | /O(1)./ The empty Builder, satisfying
94+-- | /O(1)./ The empty @Builder@, satisfying
82--
95--
83-- * @'toLazyText' 'empty' = 'L.empty'@
96-- * @'toLazyText' 'empty' = 'L.empty'@
84--
97--
@@ -86,7 +99,7 @@ empty :: Builder
86empty = Builder id
99empty = Builder id
87{-# INLINE empty #-}
100{-# INLINE empty #-}
88
101
89−-- | /O(1)./ A Builder taking a single character, satisfying
102+-- | /O(1)./ A @Builder@ taking a single character, satisfying
90--
103--
91-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
104-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
92--
105--
@@ -96,7 +109,7 @@ singleton c = putChar c
96
109
97------------------------------------------------------------------------
110------------------------------------------------------------------------
98
111
99−-- | /O(1)./ The concatenation of two Builders, an associative
112+-- | /O(1)./ The concatenation of two builders, an associative
100-- operation with identity 'empty', satisfying
113-- operation with identity 'empty', satisfying
101--
114--
102-- * @'toLazyText' ('append' x y) = 'L.append' ('toLazyText' x) ('toLazyText' y)@
115-- * @'toLazyText' ('append' x y) = 'L.append' ('toLazyText' x) ('toLazyText' y)@
@@ -107,12 +120,12 @@ append (Builder f) (Builder g) = Builder (f . g)
107
120
108-- TODO: Experiment to find the right threshold.
121-- TODO: Experiment to find the right threshold.
109copyLimit :: Int
122copyLimit :: Int
110−copyLimit = 128
123+copyLimit = 128
111
124
112−-- This function attempts to merge small Texts instead of treating the
125+-- This function attempts to merge small @Text@ values instead of
113−-- text as its own chunk. We may not always want this.
126+-- treating each value as its own chunk. We may not always want this.
114
127
115−-- | /O(1)./ A Builder taking a 'S.Text', satisfying
128+-- | /O(1)./ A @Builder@ taking a 'S.Text', satisfying
116--
129--
117-- * @'toLazyText' ('fromText' t) = 'L.fromChunks' [t]@
130-- * @'toLazyText' ('fromText' t) = 'L.fromChunks' [t]@
118--
131--
@@ -128,7 +141,7 @@ fromText t@(Text arr off l)
128 fromText (S.pack s) = fromString s
141 fromText (S.pack s) = fromString s
129 #-}
142 #-}
130
143
131−-- | /O(1)./ A Builder taking a 'String', satisfying
144+-- | /O(1)./ A Builder taking a @String@, satisfying
132--
145--
133-- * @'toLazyText' ('fromString' s) = 'L.fromChunks' [S.pack s]@
146-- * @'toLazyText' ('fromString' s) = 'L.fromChunks' [S.pack s]@
134--
147--
@@ -150,7 +163,7 @@ fromString str = Builder $ \k (Buffer p0 o0 u0 l0) ->
150 chunkSize = smallChunkSize
163 chunkSize = smallChunkSize
151{-# INLINE fromString #-}
164{-# INLINE fromString #-}
152
165
153−-- | /O(1)./ A Builder taking a lazy 'L.Text', satisfying
166+-- | /O(1)./ A @Builder@ taking a lazy @Text@, satisfying
154--
167--
155-- * @'toLazyText' ('fromLazyText' t) = t@
168-- * @'toLazyText' ('fromLazyText' t) = t@
156--
169--
@@ -168,15 +181,15 @@ data Buffer s = Buffer {-# UNPACK #-} !(A.MArray s)
168
181
169------------------------------------------------------------------------
182------------------------------------------------------------------------
170
183
171−-- | /O(n)./ Extract a lazy 'L.Text' from a 'Builder' with a default
184+-- | /O(n)./ Extract a lazy @Text@ from a @Builder@ with a default
172-- buffer size. The construction work takes place if and when the
185-- buffer size. The construction work takes place if and when the
173−-- relevant part of the lazy 'L.Text' is demanded.
186+-- relevant part of the lazy @Text@ is demanded.
174toLazyText :: Builder -> L.Text
187toLazyText :: Builder -> L.Text
175toLazyText = toLazyTextWith smallChunkSize
188toLazyText = toLazyTextWith smallChunkSize
176
189
177−-- | /O(n)./ Extract a lazy 'L.Text' from a 'Builder', using the given
190+-- | /O(n)./ Extract a lazy @Text@ from a @Builder@, using the given
178-- size for the initial buffer. The construction work takes place if
191-- size for the initial buffer. The construction work takes place if
179−-- and when the relevant part of the lazy 'L.Text' is demanded.
192+-- and when the relevant part of the lazy @Text@ is demanded.
180--
193--
181-- If the initial buffer is too small to hold all data, subsequent
194-- If the initial buffer is too small to hold all data, subsequent
182-- buffers will be the default buffer size.
195-- buffers will be the default buffer size.
@@ -184,8 +197,8 @@ toLazyTextWith :: Int -> Builder -> L.Text
184toLazyTextWith chunkSize m = L.fromChunks (runST $
197toLazyTextWith chunkSize m = L.fromChunks (runST $
185 newBuffer chunkSize >>= runBuilder (m `append` flush) (const (return [])))
198 newBuffer chunkSize >>= runBuilder (m `append` flush) (const (return [])))
186
199
187−-- | /O(1)./ Pop the 'S.Text' we have constructed so far, if any,
200+-- | /O(1)./ Pop the strict @Text@ we have constructed so far, if any,
188−-- yielding a new chunk in the result lazy 'L.Text'.
201+-- yielding a new chunk in the result lazy @Text@.
189flush :: Builder
202flush :: Builder
190flush = Builder $ \ k buf@(Buffer p o u l) ->
203flush = Builder $ \ k buf@(Buffer p o u l) ->
191 if u == 0
204 if u == 0