diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for array-builder
 
+## 0.1.3.0 -- 2022-04-11
+
+* Add `length`, `shortText`, `char`, `word32Dec`, `word64Dec`, `int32Dec`, `int64Dec`
+  to `Data.Builder.Catenable.Text`.
+* Add `length`, `bytes`, and `byteArray` to `Data.Builder.Catenable.Bytes`.
+
 ## 0.1.2.0 -- 2022-08-09
 
 * Add `Data.Builder.Catenable` module.
diff --git a/array-builder.cabal b/array-builder.cabal
--- a/array-builder.cabal
+++ b/array-builder.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.2
 name: array-builder
-version: 0.1.2.0
+version: 0.1.3.0
 synopsis: Builders for arrays
 homepage: https://github.com/andrewthad/array-builder
 bug-reports: https://github.com/andrewthad/array-builder/issues
@@ -26,7 +26,9 @@
     , base >=4.12 && <5
     , bytebuild >=0.3.5
     , byteslice >=0.2.7
-    , primitive >=0.6.4 && <0.8
+    , bytestring
+    , natural-arithmetic >=0.1.3
+    , primitive >=0.6.4 && <0.10
     , run-st >=0.1 && <0.2
     , text-short >=0.1.3
   hs-source-dirs: src
diff --git a/src/Data/Builder/Catenable.hs b/src/Data/Builder/Catenable.hs
--- a/src/Data/Builder/Catenable.hs
+++ b/src/Data/Builder/Catenable.hs
@@ -34,6 +34,10 @@
     -- * Convenient infix operators
   , pattern (:<)
   , pattern (:>)
+    -- * Functions
+  , singleton
+  , doubleton
+  , tripleton
     -- * Run
   , run
   ) where
@@ -93,3 +97,15 @@
   Append x y -> do
     bldr1 <- pushCatenable bldr0 x
     pushCatenable bldr1 y
+
+singleton :: a -> Builder a
+{-# inline singleton #-}
+singleton a = Cons a Empty
+
+doubleton :: a -> a -> Builder a
+{-# inline doubleton #-}
+doubleton a b = Cons a (Cons b Empty)
+
+tripleton :: a -> a -> a -> Builder a
+{-# inline tripleton #-}
+tripleton a b c = Append (Cons a (Cons b Empty)) (Cons c Empty)
diff --git a/src/Data/Builder/Catenable/Bytes.hs b/src/Data/Builder/Catenable/Bytes.hs
--- a/src/Data/Builder/Catenable/Bytes.hs
+++ b/src/Data/Builder/Catenable/Bytes.hs
@@ -10,12 +10,21 @@
   , pattern (:>)
     -- * Run
   , run
+    -- * Properties
+  , length
+    -- * Create
+  , bytes
+  , byteArray
   ) where
 
+import Prelude hiding (length)
+
 import Control.Monad.ST (ST,runST)
 import Data.Bytes (Bytes)
 import Data.Bytes.Chunks (Chunks(ChunksNil))
+import Data.Primitive (ByteArray)
 
+import qualified Data.Bytes as Bytes
 import qualified Data.Bytes.Builder as BB
 import qualified Data.Bytes.Builder.Unsafe as BBU
 
@@ -42,6 +51,14 @@
 pattern (:>) :: Builder -> Bytes -> Builder
 pattern (:>) x y = Snoc x y
 
+-- | Number of bytes in the sequence.
+length :: Builder -> Int
+length b0 = case b0 of
+  Empty -> 0
+  Cons x b1 -> Bytes.length x + length b1
+  Snoc b1 x -> Bytes.length x + length b1
+  Append x y -> length x + length y
+
 run :: Builder -> Chunks
 {-# noinline run #-}
 run b = runST $ do
@@ -62,4 +79,8 @@
     bldr1 <- pushCatenable bldr0 x
     pushCatenable bldr1 y
 
+bytes :: Bytes -> Builder
+bytes !b = Cons b Empty
 
+byteArray :: ByteArray -> Builder
+byteArray !b = Cons (Bytes.fromByteArray b) Empty
diff --git a/src/Data/Builder/Catenable/Text.hs b/src/Data/Builder/Catenable/Text.hs
--- a/src/Data/Builder/Catenable/Text.hs
+++ b/src/Data/Builder/Catenable/Text.hs
@@ -10,16 +10,35 @@
   , pattern (:>)
     -- * Run
   , run
+    -- * Properties
+  , length
+    -- * Create
+  , shortText
+  , char
+  , word32Dec
+  , word64Dec
+  , int32Dec
+  , int64Dec
   ) where
 
+import Prelude hiding (length)
+
 import Control.Monad.ST (ST,runST)
-import Data.Text.Short (ShortText)
+import Data.ByteString.Short.Internal (ShortByteString(SBS))
 import Data.Bytes.Chunks (Chunks(ChunksNil))
+import Data.Int (Int32,Int64)
+import Data.Primitive (ByteArray(ByteArray))
 import Data.String (IsString(fromString))
+import Data.Text.Short (ShortText)
+import Data.Word (Word32,Word64)
 
-import qualified Data.Text.Short as TS
+import qualified Arithmetic.Nat as Nat
 import qualified Data.Bytes.Builder as BB
+import qualified Data.Bytes.Builder.Bounded as Bounded
 import qualified Data.Bytes.Builder.Unsafe as BBU
+import qualified Data.Bytes.Chunks as Chunks
+import qualified Data.Text.Short as TS
+import qualified Data.Text.Short.Unsafe as TS
 
 infixr 5 :<
 infixl 5 :>
@@ -30,6 +49,32 @@
   | Snoc !Builder !ShortText
   | Append !Builder !Builder
 
+shortText :: ShortText -> Builder
+shortText !t = Cons t Empty
+
+char :: Char -> Builder
+char !c = Cons (TS.singleton c) Empty
+
+word32Dec :: Word32 -> Builder
+word32Dec !i = Cons (ba2st (Bounded.run Nat.constant (Bounded.word32Dec i))) Empty
+
+word64Dec :: Word64 -> Builder
+word64Dec !i = Cons (ba2st (Bounded.run Nat.constant (Bounded.word64Dec i))) Empty
+
+int32Dec :: Int32 -> Builder
+int32Dec !i = Cons (ba2st (Bounded.run Nat.constant (Bounded.int32Dec i))) Empty
+
+int64Dec :: Int64 -> Builder
+int64Dec !i = Cons (ba2st (Bounded.run Nat.constant (Bounded.int64Dec i))) Empty
+
+-- | Number of Unicode code points in the sequence.
+length :: Builder -> Int
+length b0 = case b0 of
+  Empty -> 0
+  Cons x b1 -> TS.length x + length b1
+  Snoc b1 x -> TS.length x + length b1
+  Append x y -> length x + length y
+
 -- | Note: The choice of appending to the left side of @Empty@ instead
 -- of the right side of arbitrary. Under ordinary use, this difference
 -- cannot be observed by the user.
@@ -44,6 +89,18 @@
   {-# inline (<>) #-}
   (<>) = Append
 
+-- | Not structural equality. Converts builders to chunks and then
+-- compares the chunks.
+instance Eq Builder where
+  a == b = run a == run b
+
+instance Show Builder where
+  show b = TS.unpack (ba2st (Chunks.concatU (run b)))
+
+ba2st :: ByteArray -> ShortText
+{-# inline ba2st #-}
+ba2st (ByteArray x) = TS.fromShortByteStringUnsafe (SBS x)
+
 pattern (:<) :: ShortText -> Builder -> Builder
 pattern (:<) x y = Cons x y
 
@@ -72,4 +129,3 @@
   Append x y -> do
     bldr1 <- pushCatenable bldr0 x
     pushCatenable bldr1 y
-
