diff --git a/core-text.cabal b/core-text.cabal
--- a/core-text.cabal
+++ b/core-text.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           core-text
-version:        0.3.7.2
+version:        0.3.8.0
 synopsis:       A rope type based on a finger tree over UTF-8 fragments
 description:    A rope data type for text, built as a finger tree over UTF-8 text
                 fragments. The package also includes utiltiy functions for breaking and
diff --git a/lib/Core/Text/Rope.hs b/lib/Core/Text/Rope.hs
--- a/lib/Core/Text/Rope.hs
+++ b/lib/Core/Text/Rope.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ImportQualifiedPost #-}
 {-# LANGUAGE InstanceSigs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE StrictData #-}
@@ -102,17 +103,18 @@
 
 import Control.DeepSeq (NFData (..))
 import Core.Text.Bytes
-import qualified Data.ByteString as B (ByteString)
-import qualified Data.ByteString.Builder as B (
+import Data.ByteString qualified as B (ByteString)
+import Data.ByteString.Builder qualified as B (
+    Builder,
     hPutBuilder,
     toLazyByteString,
  )
-import qualified Data.ByteString.Lazy as L (
+import Data.ByteString.Lazy qualified as L (
     ByteString,
     foldrChunks,
     toStrict,
  )
-import qualified Data.FingerTree as F (
+import Data.FingerTree qualified as F (
     FingerTree,
     Measured (..),
     SearchResult (..),
@@ -129,19 +131,19 @@
 import Data.Foldable (foldl', toList)
 import Data.Hashable (Hashable, hashWithSalt)
 import Data.String (IsString (..))
-import qualified Data.Text as T (Text)
-import qualified Data.Text.Lazy as U (
+import Data.Text qualified as T (Text)
+import Data.Text.Lazy qualified as U (
     Text,
     foldrChunks,
     fromChunks,
     toStrict,
  )
-import qualified Data.Text.Lazy.Builder as U (
+import Data.Text.Lazy.Builder qualified as U (
     Builder,
     fromText,
     toLazyText,
  )
-import qualified Data.Text.Short as S (
+import Data.Text.Short qualified as S (
     ShortText,
     any,
     append,
@@ -159,7 +161,7 @@
     uncons,
     unpack,
  )
-import qualified Data.Text.Short.Unsafe as S (fromByteStringUnsafe)
+import Data.Text.Short.Unsafe qualified as S (fromByteStringUnsafe)
 import GHC.Generics (Generic)
 import Prettyprinter (Pretty (..), emptyDoc)
 import System.IO (Handle)
@@ -551,6 +553,20 @@
         Just piece -> Rope ((F.|>) x piece)
         Nothing -> (Rope x) -- bad
 
+-- | from "Data.ByteString.Builder"
+instance Textual B.Builder where
+    fromRope = foldr g mempty . unRope
+      where
+        g piece built = (<>) (S.toBuilder piece) built
+    intoRope =
+        Rope
+            . ( L.foldrChunks
+                    ( (F.<|) . S.fromByteStringUnsafe
+                    )
+                    F.empty
+              )
+            . B.toLazyByteString
+
 -- | from "Data.ByteString.Lazy"
 instance Textual L.ByteString where
     fromRope = B.toLazyByteString . foldr g mempty . unRope
@@ -606,11 +622,9 @@
 'Data.ByteString.Short.ShortByteString' to 'Data.ByteString.Builder.Builder'
 to the 'System.IO.Handle''s output buffer in one go.
 
-If you're working in the
-<https://hackage.haskell.org/package/core-program/docs/Core-Program-Execute.html#t:Program
-Program> monad, then
-<https://hackage.haskell.org/package/core-program/docs/Core-Program-Logging.html#v:write
-write> provides an efficient way to write a @Rope@ to @stdout@.
+If you're working in the __core-program__ 'Core.Program.Execute.Program' @τ@
+monad, then the 'Core.Program.Logging.write' function there provides an
+efficient way to write a 'Rope' to @stdout@.
 -}
 hWrite :: Handle -> Rope -> IO ()
 hWrite handle (Rope x) = B.hPutBuilder handle (foldr j mempty x)
diff --git a/lib/Core/Text/Utilities.hs b/lib/Core/Text/Utilities.hs
--- a/lib/Core/Text/Utilities.hs
+++ b/lib/Core/Text/Utilities.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ImportQualifiedPost #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
@@ -52,13 +53,13 @@
 import Core.Text.Parsing
 import Core.Text.Rope
 import Data.Bits (Bits (..))
-import qualified Data.ByteString as B (ByteString, length, splitAt, unpack)
+import Data.ByteString qualified as B (ByteString, length, splitAt, unpack)
 import Data.Char (intToDigit)
-import qualified Data.FingerTree as F (ViewL (..), viewl, (<|))
+import Data.FingerTree qualified as F (ViewL (..), viewl, (<|))
 import Data.Kind (Type)
-import qualified Data.List as List (dropWhileEnd, foldl', splitAt)
-import qualified Data.Text as T
-import qualified Data.Text.Short as S (
+import Data.List qualified as List (dropWhileEnd, foldl', splitAt)
+import Data.Text qualified as T
+import Data.Text.Short qualified as S (
     ShortText,
     replicate,
     singleton,
@@ -164,10 +165,9 @@
   where
     go [] = []
     go [x] = [softline' <> x]
-    go xs =
-        let (one : two : [], remainder) = List.splitAt 2 xs
-         in group (one <> spacer <> two) : go remainder
-
+    go xs = case List.splitAt 2 xs of
+        (one : two : [], remainder) -> group (one <> spacer <> two) : go remainder
+        _ -> [] -- unreachable
     spacer = flatAlt softline' "  "
 
 byteChunk :: B.ByteString -> [B.ByteString]
@@ -316,7 +316,6 @@
 λ> __oxford []__
 ""
 @
-
 -}
 oxford :: [Rope] -> Rope
 oxford [] = emptyRope
