diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
 Brick changelog
 ---------------
 
+0.46
+----
+
+Performance improvements:
+ * The box combinators `<=>`, `<+>`, `vBox`, and `hBox` got GHC rewrite
+   rules that will optimize away redundant boxes. This change improves
+   performance for chains of `<+>` or `<=>` as well as nested boxes
+   using `hBox` and `vBox`. Previously chains of e.g. `<+>` produced
+   binary trees of boxes that incurred more rendering overhead. Those
+   are now optimized away.
+
+API changes:
+ * Data.Text.Markup: renamed `empty` to `isEmpty`
+
 0.45
 ----
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -69,6 +69,7 @@
  * `towerHanoi`, animated solutions to The Tower of Hanoi: https://github.com/shajenM/projects/tree/master/towerHanoi
  * `VOIDSPACE`, a space-themed typing-tutor game: https://github.com/ChrisPenner/void-space
  * `solitaire`, the card game: https://github.com/ambuc/solitaire
+ * `sudoku-tui`, a Sudoku implementation: https://github.com/evanrelf/sudoku-tui
 
 Getting Started
 ---------------
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.45
+version:             0.46
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal applications painlessly with 'brick'! You write an
diff --git a/src/Brick/Widgets/Core.hs b/src/Brick/Widgets/Core.hs
--- a/src/Brick/Widgets/Core.hs
+++ b/src/Brick/Widgets/Core.hs
@@ -422,16 +422,20 @@
 -- in the specified order (uppermost first). Defers growth policies to
 -- the growth policies of the contained widgets (if any are greedy, so
 -- is the box).
+{-# NOINLINE vBox #-}
 vBox :: [Widget n] -> Widget n
 vBox [] = emptyWidget
+vBox [a] = a
 vBox pairs = renderBox vBoxRenderer pairs
 
 -- | Horizontal box layout: put the specified widgets next to each other
 -- in the specified order (leftmost first). Defers growth policies to
 -- the growth policies of the contained widgets (if any are greedy, so
 -- is the box).
+{-# NOINLINE hBox #-}
 hBox :: [Widget n] -> Widget n
 hBox [] = emptyWidget
+hBox [a] = a
 hBox pairs = renderBox hBoxRenderer pairs
 
 -- | The process of rendering widgets in a box layout is exactly the
@@ -1227,6 +1231,7 @@
 -- | Horizontal box layout: put the specified widgets next to each other
 -- in the specified order. Defers growth policies to the growth policies
 -- of both widgets.  This operator is a binary version of 'hBox'.
+{-# NOINLINE (<+>) #-}
 (<+>) :: Widget n
       -- ^ Left
       -> Widget n
@@ -1237,9 +1242,21 @@
 -- | Vertical box layout: put the specified widgets one above the other
 -- in the specified order. Defers growth policies to the growth policies
 -- of both widgets.  This operator is a binary version of 'vBox'.
+{-# NOINLINE (<=>) #-}
 (<=>) :: Widget n
       -- ^ Top
       -> Widget n
       -- ^ Bottom
       -> Widget n
 (<=>) a b = vBox [a, b]
+
+{-# RULES
+"baseHbox" forall a b   . a <+> b                 = hBox [a, b]
+"hBox2"    forall as bs . hBox [hBox as, hBox bs] = hBox (as ++ bs)
+"hboxL"    forall as b  . hBox [hBox as, b]       = hBox (as ++ [b])
+"hboxR"    forall a bs  . hBox [a, hBox bs]       = hBox (a : bs)
+"baseVbox" forall a b   . a <=> b                 = vBox [a, b]
+"vBox2"    forall as bs . vBox [vBox as, vBox bs] = vBox (as ++ bs)
+"vboxL"    forall as b  . vBox [vBox as, b]       = vBox (as ++ [b])
+"vboxR"    forall a bs  . vBox [a, vBox bs]       = vBox (a : bs)
+#-}
diff --git a/src/Brick/Widgets/List.hs b/src/Brick/Widgets/List.hs
--- a/src/Brick/Widgets/List.hs
+++ b/src/Brick/Widgets/List.hs
@@ -9,6 +9,14 @@
 {-# LANGUAGE DeriveGeneric #-}
 -- | This module provides a scrollable list type and functions for
 -- manipulating and rendering it.
+--
+-- Note that lenses are provided for direct manipulation purposes, but
+-- lenses are *not* safe and should be used with care. (For example,
+-- 'listElementsL' permits direct manipulation of the list container
+-- without performing bounds checking on the selected index.) If you
+-- need a safe API, consider one of the various functions for list
+-- manipulation. For example, instead of 'listElementsL', consider
+-- 'listReplace'.
 module Brick.Widgets.List
   ( GenericList
   , List
@@ -265,6 +273,15 @@
 -- for drawing and 'listItemHeight'. At most, it will evaluate up to
 -- element @(i + h + 1)@ where @i@ is the selected index and @h@ is the
 -- available height.
+--
+-- Note that this function renders the list with the 'listAttr' as
+-- the default attribute and then uses 'listSelectedAttr' as the
+-- default attribute for the selected item if the list is not focused
+-- or 'listSelectedFocusedAttr' otherwise. This is provided as a
+-- convenience so that the item rendering function doesn't have to be
+-- concerned with attributes, but if those attributes are undesirable
+-- for your purposes, 'forceAttr' can always be used by the item
+-- rendering function to ensure that another attribute is used instead.
 renderList :: (Traversable t, Splittable t, Ord n, Show n)
            => (Bool -> e -> Widget n)
            -- ^ Rendering function, True for the selected element
diff --git a/src/Data/Text/Markup.hs b/src/Data/Text/Markup.hs
--- a/src/Data/Text/Markup.hs
+++ b/src/Data/Text/Markup.hs
@@ -12,7 +12,7 @@
   , fromList
   , fromText
   , toText
-  , empty
+  , isEmpty
   , (@@)
   )
 where
@@ -54,8 +54,8 @@
 toText = T.concat . (fst <$>) . concat . markupToList
 
 -- | Test whether the markup is empty.
-empty :: Markup a -> Bool
-empty (Markup ls) = null ls
+isEmpty :: Markup a -> Bool
+isEmpty (Markup ls) = null ls
 
 -- | Set the metadata for a range of character positions in a piece of
 -- markup. This is useful for, e.g., syntax highlighting.
