-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Builder for Text based on linear types -- -- Strict Text builder, which hides mutable buffer behind linear types -- and takes amortized linear time. @package text-builder-linear @version 0.1 -- | Low-level routines for Buffer manipulations. module Data.Text.Builder.Linear.Core -- | Internally Buffer is a mutable buffer. If a client gets hold of -- a variable of type Buffer, they'd be able to pass a mutable -- buffer to concurrent threads. That's why API below is carefully -- designed to prevent such possibility: clients always work with linear -- functions BufferBuffer instead and run them on an -- empty Buffer to extract results. -- -- In terms of linear-base Buffer is Consumable -- (see consumeBuffer) and Dupable (see -- dupBuffer), but not Movable. -- --
--   >>> :set -XOverloadedStrings -XLinearTypes
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> '!' .<| "foo" <| (b |> "bar" |>. '.'))
--   "!foobar."
--   
-- -- Remember: this is a strict builder, so on contrary to -- Data.Text.Lazy.Builder for optimal performance you should use -- strict left folds instead of lazy right ones. -- -- Starting from GHC 9.2, Buffer is an unlifted datatype, so you -- can put it into an unboxed tuple (# ..., ... #), but not into -- (..., ...). data Buffer ∷ TYPE ('BoxedRep 'Unlifted) -- | Run a linear function on an empty Buffer, producing -- Text. -- -- Be careful to write runBuffer (b -> ...) instead of -- runBuffer $ b -> ..., because current implementation of -- linear types lacks special support for ($). Another option is -- to enable {-# LANGUAGE BlockArguments #-} and write -- runBuffer b -> .... Alternatively, you can import -- Prelude.Linear.($) from linear-base. -- -- runBuffer is similar in spirit to mutable arrays API in -- Data.Array.Mutable.Linear, which provides functions like -- fromList ∷ [a] → (Vector a ⊸ -- Ur b) ⊸ Ur b. Here the initial buffer is -- always empty and b is Text. Since Text is -- Movable, Text and Ur Text are -- equivalent. runBuffer :: (Buffer ⊸ Buffer) ⊸ Text -- | Duplicate builder. Feel free to process results in parallel threads. -- Similar to Data.Unrestricted.Linear.Dupable from -- linear-base. -- -- It is a bit tricky to use because of current limitations of -- linear types with regards to let and where. E. g., -- one cannot write -- --
--   let (# b1, b2 #) = dupBuffer b in ("foo" <| b1) >< (b2 |> "bar")
--   
-- -- Instead write: -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XUnboxedTuples
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> (\(# b1, b2 #) -> ("foo" <| b1) >< (b2 |> "bar")) (dupBuffer b))
--   "foobar"
--   
-- -- Note the unboxed tuple: starting from GHC 9.2, Buffer is an -- unlifted datatype, so it cannot be put into (..., ...). dupBuffer :: Buffer ⊸ (# Buffer, Buffer #) -- | Consume buffer linearly, similar to -- Data.Unrestricted.Linear.Consumable from -- linear-base. consumeBuffer :: Buffer ⊸ () -- | Erase buffer's content, replacing it with an empty Text. eraseBuffer :: Buffer ⊸ Buffer -- | Return buffer's size in bytes (not in Chars). This could -- be useful to implement a lazy builder atop of a strict one. byteSizeOfBuffer :: Buffer ⊸ (# Buffer, Word #) -- | Return buffer's length in Chars (not in bytes). This could be -- useful to implement dropEndBuffer and takeEndBuffer, -- e. g., -- --
--   import Data.Unrestricted.Linear
--   
--   dropEndBuffer :: Word -> Buffer %1 -> Buffer
--   dropEndBuffer n buf =
--     ((# buf', len #) -> case move len of Ur len' -> takeBuffer (len' - n) buf')
--       (lengthOfBuffer buf)
--   
lengthOfBuffer :: Buffer ⊸ (# Buffer, Word #) -- | Slice Buffer by dropping given number of Chars. dropBuffer :: Word → Buffer ⊸ Buffer -- | Slice Buffer by taking given number of Chars. takeBuffer :: Word → Buffer ⊸ Buffer -- | Low-level routine to append data of unknown size to a Buffer. appendBounded :: Int → (∀ s. MArray s → Int → ST s Int) → Buffer ⊸ Buffer -- | Low-level routine to append data of known size to a Buffer. appendExact :: Int → (∀ s. MArray s → Int → ST s ()) → Buffer ⊸ Buffer -- | Low-level routine to prepend data of unknown size to a Buffer. prependBounded :: Int → (∀ s. MArray s → Int → ST s Int) → (∀ s. MArray s → Int → ST s Int) → Buffer ⊸ Buffer -- | Low-level routine to append data of unknown size to a Buffer. prependExact :: Int → (∀ s. MArray s → Int → ST s ()) → Buffer ⊸ Buffer -- | Concatenate two Buffers, potentially mutating both of them. -- -- You likely need to use dupBuffer to get hold on two builders at -- once: -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XUnboxedTuples
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> (\(# b1, b2 #) -> ("foo" <| b1) >< (b2 |> "bar")) (dupBuffer b))
--   "foobar"
--   
(><) :: Buffer ⊸ Buffer ⊸ Buffer infix 6 >< -- | Buffer for strict Text, based on linear types. module Data.Text.Builder.Linear.Buffer -- | Internally Buffer is a mutable buffer. If a client gets hold of -- a variable of type Buffer, they'd be able to pass a mutable -- buffer to concurrent threads. That's why API below is carefully -- designed to prevent such possibility: clients always work with linear -- functions BufferBuffer instead and run them on an -- empty Buffer to extract results. -- -- In terms of linear-base Buffer is Consumable -- (see consumeBuffer) and Dupable (see -- dupBuffer), but not Movable. -- --
--   >>> :set -XOverloadedStrings -XLinearTypes
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> '!' .<| "foo" <| (b |> "bar" |>. '.'))
--   "!foobar."
--   
-- -- Remember: this is a strict builder, so on contrary to -- Data.Text.Lazy.Builder for optimal performance you should use -- strict left folds instead of lazy right ones. -- -- Starting from GHC 9.2, Buffer is an unlifted datatype, so you -- can put it into an unboxed tuple (# ..., ... #), but not into -- (..., ...). data Buffer ∷ TYPE ('BoxedRep 'Unlifted) -- | Run a linear function on an empty Buffer, producing -- Text. -- -- Be careful to write runBuffer (b -> ...) instead of -- runBuffer $ b -> ..., because current implementation of -- linear types lacks special support for ($). Another option is -- to enable {-# LANGUAGE BlockArguments #-} and write -- runBuffer b -> .... Alternatively, you can import -- Prelude.Linear.($) from linear-base. -- -- runBuffer is similar in spirit to mutable arrays API in -- Data.Array.Mutable.Linear, which provides functions like -- fromList ∷ [a] → (Vector a ⊸ -- Ur b) ⊸ Ur b. Here the initial buffer is -- always empty and b is Text. Since Text is -- Movable, Text and Ur Text are -- equivalent. runBuffer :: (Buffer ⊸ Buffer) ⊸ Text -- | Duplicate builder. Feel free to process results in parallel threads. -- Similar to Data.Unrestricted.Linear.Dupable from -- linear-base. -- -- It is a bit tricky to use because of current limitations of -- linear types with regards to let and where. E. g., -- one cannot write -- --
--   let (# b1, b2 #) = dupBuffer b in ("foo" <| b1) >< (b2 |> "bar")
--   
-- -- Instead write: -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XUnboxedTuples
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> (\(# b1, b2 #) -> ("foo" <| b1) >< (b2 |> "bar")) (dupBuffer b))
--   "foobar"
--   
-- -- Note the unboxed tuple: starting from GHC 9.2, Buffer is an -- unlifted datatype, so it cannot be put into (..., ...). dupBuffer :: Buffer ⊸ (# Buffer, Buffer #) -- | Consume buffer linearly, similar to -- Data.Unrestricted.Linear.Consumable from -- linear-base. consumeBuffer :: Buffer ⊸ () -- | Erase buffer's content, replacing it with an empty Text. eraseBuffer :: Buffer ⊸ Buffer -- | This is just a normal foldl', but with a linear arrow and -- potentially unlifted accumulator. foldlIntoBuffer :: (Buffer ⊸ a → Buffer) → Buffer ⊸ [a] → Buffer -- | Append Text suffix to a Buffer by mutating it. If a -- suffix is statically known, consider using (|>#) for optimal -- performance. -- --
--   >>> :set -XOverloadedStrings -XLinearTypes
--   
--   >>> runBuffer (\b -> b |> "foo" |> "bar")
--   "foobar"
--   
(|>) :: Buffer ⊸ Text → Buffer infixl 6 |> -- | Append Char to a Buffer by mutating it. -- --
--   >>> :set -XLinearTypes
--   
--   >>> runBuffer (\b -> b |>. 'q' |>. 'w')
--   "qw"
--   
(|>.) :: Buffer ⊸ Char → Buffer infixl 6 |>. -- | Append a null-terminated UTF-8 string to a Buffer by mutating -- it. E. g., -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XMagicHash
--   
--   >>> runBuffer (\b -> b |># "foo"# |># "bar"#)
--   "foobar"
--   
-- -- The literal string must not contain zero bytes \0, this -- condition is not checked. -- -- Note the inconsistency in naming: unfortunately, GHC parser does not -- allow for #<|. (|>#) :: Buffer ⊸ Addr# → Buffer infixl 6 |># -- | Prepend Text prefix to a Buffer by mutating it. If a -- prefix is statically known, consider using (<|#) for optimal -- performance. -- --
--   >>> :set -XOverloadedStrings -XLinearTypes
--   
--   >>> runBuffer (\b -> "foo" <| "bar" <| b)
--   "foobar"
--   
(<|) :: Text → Buffer ⊸ Buffer infixr 6 <| -- | Prepend Char to a Buffer by mutating it. -- --
--   >>> :set -XLinearTypes
--   
--   >>> runBuffer (\b -> 'q' .<| 'w' .<| b)
--   "qw"
--   
(.<|) :: Char → Buffer ⊸ Buffer infixr 6 .<| -- | Prepend a null-terminated UTF-8 string to a Buffer by mutating -- it. E. g., -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XMagicHash
--   
--   >>> runBuffer (\b -> "foo"# <|# "bar"# <|# b)
--   "foobar"
--   
-- -- The literal string must not contain zero bytes \0, this -- condition is not checked. (<|#) :: Addr# → Buffer ⊸ Buffer infixr 6 <|# -- | Concatenate two Buffers, potentially mutating both of them. -- -- You likely need to use dupBuffer to get hold on two builders at -- once: -- --
--   >>> :set -XOverloadedStrings -XLinearTypes -XUnboxedTuples
--   
--   >>> import Data.Text.Builder.Linear.Buffer
--   
--   >>> runBuffer (\b -> (\(# b1, b2 #) -> ("foo" <| b1) >< (b2 |> "bar")) (dupBuffer b))
--   "foobar"
--   
(><) :: Buffer ⊸ Buffer ⊸ Buffer infix 6 >< -- | Append decimal number. (|>$) :: (Integral a, FiniteBits a) ⇒ Buffer ⊸ a → Buffer infixl 6 |>$ -- | Prepend decimal number. ($<|) :: (Integral a, FiniteBits a) ⇒ a → Buffer ⊸ Buffer infixr 6 $<| -- | Append double. (|>%) :: Buffer ⊸ Double → Buffer infixl 6 |>% -- | Prepend double (%<|) :: Double → Buffer ⊸ Buffer infixr 6 %<| -- | Append hexadecimal number. (|>&) :: (Integral a, FiniteBits a) ⇒ Buffer ⊸ a → Buffer infixl 6 |>& -- | Prepend hexadecimal number. (&<|) :: (Integral a, FiniteBits a) ⇒ a → Buffer ⊸ Buffer infixr 6 &<| -- | Append given number of spaces. (|>…) :: Buffer ⊸ Word → Buffer infixr 6 |>… -- | Prepend given number of spaces. (…<|) :: Word → Buffer ⊸ Buffer infixr 6 …<| -- | Builder for strict Text, based on linear types. It's -- consistently outperforms Data.Text.Lazy.Builder from -- text as well as a strict builder from text-builder, -- and scales better. module Data.Text.Builder.Linear -- | Thin wrapper over Buffer with a handy Semigroup -- instance. -- --
--   >>> :set -XOverloadedStrings -XMagicHash
--   
--   >>> fromText "foo" <> fromChar '_' <> fromAddr "bar"#
--   "foo_bar"
--   
-- -- Remember: this is a strict builder, so on contrary to -- Data.Text.Lazy.Builder for optimal performance you should use -- strict left folds instead of lazy right ones. -- -- Note that (similar to other builders) concatenation of Builders -- allocates thunks. This is to a certain extent mitigated by aggressive -- inlining, but it is faster to use Buffer directly. newtype Builder Builder :: (Buffer ⊸ Buffer) → Builder [unBuilder] :: Builder → Buffer ⊸ Buffer -- | Run Builder computation on an empty Buffer, returning -- Text. -- --
--   >>> :set -XOverloadedStrings -XMagicHash
--   
--   >>> runBuilder (fromText "foo" <> fromChar '_' <> fromAddr "bar"#)
--   "foo_bar"
--   
-- -- This function has a polymorphic arrow and thus can be used both in -- usual and linear contexts. runBuilder :: ∀ m. Builder %m → Text -- | Create Builder, containing a given Text. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> fromText "foo" <> fromText "bar"
--   "foobar"
--   
fromText :: Text → Builder -- | Create Builder, containing a given Char. -- --
--   >>> fromChar 'x' <> fromChar 'y'
--   "xy"
--   
fromChar :: Char → Builder -- | Create Builder, containing a null-terminated UTF-8 string, -- specified by Addr#. -- --
--   >>> :set -XMagicHash
--   
--   >>> fromAddr "foo"# <> fromAddr "bar"#
--   "foobar"
--   
fromAddr :: Addr# → Builder -- | Create Builder, containing decimal representation of a given -- number. -- --
--   >>> fromChar 'x' <> fromDec (123 :: Int)
--   "x123"
--   
fromDec :: (Integral a, FiniteBits a) ⇒ a → Builder -- | Create Builder, containing hexadecimal representation of a -- given number. -- --
--   >>> :set -XMagicHash
--   
--   >>> fromAddr "0x"# <> fromHex (0x123def :: Int)
--   "0x123def"
--   
fromHex :: (Integral a, FiniteBits a) ⇒ a → Builder -- | Create Builder, containing a given Double. -- --
--   >>> :set -XMagicHash
--   
--   >>> fromAddr "pi="# <> fromDouble pi
--   "pi=3.141592653589793"
--   
fromDouble :: Double → Builder instance GHC.Show.Show Data.Text.Builder.Linear.Builder instance GHC.Base.Semigroup Data.Text.Builder.Linear.Builder instance GHC.Base.Monoid Data.Text.Builder.Linear.Builder instance Data.String.IsString Data.Text.Builder.Linear.Builder