diff --git a/gi-gtk-hs.cabal b/gi-gtk-hs.cabal
--- a/gi-gtk-hs.cabal
+++ b/gi-gtk-hs.cabal
@@ -1,5 +1,5 @@
 name:                gi-gtk-hs
-version:             0.3.12
+version:             0.3.13
 synopsis:            A wrapper for gi-gtk, adding a few more idiomatic API parts on top
 description:         A wrapper for gi-gtk, adding a few more idiomatic API parts on top
 homepage:            https://github.com/haskell-gi/haskell-gi
@@ -19,21 +19,22 @@
 library
   exposed-modules:     Data.GI.Gtk,
                        Data.GI.Gtk.BuildFn
-                       Data.GI.Gtk.Threading
-                       Data.GI.Gtk.ModelView.Types
+                       Data.GI.Gtk.ComboBox
                        Data.GI.Gtk.ModelView.CellLayout
                        Data.GI.Gtk.ModelView.CustomStore
-                       Data.GI.Gtk.ModelView.SeqStore
                        Data.GI.Gtk.ModelView.ForestStore
+                       Data.GI.Gtk.ModelView.SeqStore
                        Data.GI.Gtk.ModelView.TreeModel
-                       Data.GI.Gtk.ComboBox
+                       Data.GI.Gtk.ModelView.Types
+                       Data.GI.Gtk.Threading
+                       Data.GI.Gtk.Widget
 
   build-depends:       base >= 4.9 && <5,
                        base-compat >=0.9.0 && <0.13,
                        mtl >= 2.1 && <2.3,
                        transformers >=0.3.0.0 && <0.6,
                        containers >=0.5.5.1 && <0.7,
-                       text >=1.2 && <1.3,
+                       text >=1.2 && <3,
                        haskell-gi-base >=0.25.0 && <0.27,
                        gi-glib >=2.0.6 && <2.1,
                        gi-gobject >=2.0.6 && <2.1,
diff --git a/src/Data/GI/Gtk.hs b/src/Data/GI/Gtk.hs
--- a/src/Data/GI/Gtk.hs
+++ b/src/Data/GI/Gtk.hs
@@ -1,20 +1,22 @@
 module Data.GI.Gtk
     ( module GI.Gtk
-    , module Data.GI.Gtk.ModelView.Types
+    , module Data.GI.Gtk.ComboBox
     , module Data.GI.Gtk.ModelView.CellLayout
     , module Data.GI.Gtk.ModelView.CustomStore
-    , module Data.GI.Gtk.ModelView.SeqStore
     , module Data.GI.Gtk.ModelView.ForestStore
+    , module Data.GI.Gtk.ModelView.SeqStore
     , module Data.GI.Gtk.ModelView.TreeModel
-    , module Data.GI.Gtk.ComboBox
+    , module Data.GI.Gtk.ModelView.Types
+    , module Data.GI.Gtk.Widget
     ) where
 
 import GI.Gtk hiding (treeModelGetValue, treeModelGetIter)
 import Data.GI.Gtk.BuildFn
-import Data.GI.Gtk.ModelView.Types
+import Data.GI.Gtk.ComboBox
 import Data.GI.Gtk.ModelView.CellLayout
 import Data.GI.Gtk.ModelView.CustomStore
-import Data.GI.Gtk.ModelView.SeqStore
 import Data.GI.Gtk.ModelView.ForestStore
+import Data.GI.Gtk.ModelView.SeqStore
 import Data.GI.Gtk.ModelView.TreeModel
-import Data.GI.Gtk.ComboBox
+import Data.GI.Gtk.ModelView.Types
+import Data.GI.Gtk.Widget
diff --git a/src/Data/GI/Gtk/Widget.hs b/src/Data/GI/Gtk/Widget.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/GI/Gtk/Widget.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- This is needed because of using the IsWidget constraint synonym in
+-- printWidgetTree.  See
+-- https://github.com/haskell-gi/haskell-gi/pull/376#discussion_r786423429
+-- for a little discussion of this.
+{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}
+
+-- |
+-- Stability   : provisional
+-- Portability : portable (depends on GHC)
+--
+-- Helper functions for working with 'Widget's.
+
+module Data.GI.Gtk.Widget
+    ( printWidgetTree
+    ) where
+
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Data.Foldable (for_)
+import Data.GI.Base.GObject (gtypeFromInstance)
+import GI.Gtk.Objects.Widget (IsWidget, Widget, toWidget)
+import GI.Gtk (Container(Container), castTo, containerGetChildren, gtypeName, managedForeignPtr, toManagedPtr)
+
+-- | Print out a tree of decendents for a given GTK 'Widget'.  This function is
+-- mainly to help with debugging.
+--
+-- This function outputs a tree of 'Widget's like the following:
+--
+-- > GtkApplicationWindow  0x00000000068de2a0
+-- >   GtkMenuBar  0x0000000006c661d0
+-- >     GtkModelMenuItem  0x0000000006c72b00
+-- >       GtkAccelLabel  0x0000000006c73b60
+-- >     GtkModelMenuItem  0x0000000006c723c0
+-- >       GtkAccelLabel  0x0000000006c733a0
+-- >   GtkNotebook  0x0000000006b0a200
+-- >     GtkPaned  0x0000000006b073c0
+-- >       GtkScrolledWindow  0x0000000006b0c7c0
+-- >         VteTerminal  0x00000000068af4a0
+-- >       GtkScrolledWindow  0x0000000006b0c470
+-- >         VteTerminal  0x00000000068af370
+--
+-- Note that you may also be interested in
+-- <https://wiki.gnome.org/Projects/GTK/Inspector GTKInspector>, which is a
+-- built-in interactive debugger for GTK applications.
+printWidgetTree :: forall m a. (MonadIO m, IsWidget a) => a -> m ()
+printWidgetTree widget_ = do
+  widget <- toWidget widget_
+  go "" widget
+  where
+    go :: String -> Widget -> m ()
+    go indent w = do
+      type_ <- liftIO $ gtypeFromInstance w
+      name <- liftIO $ gtypeName type_
+      let ptr = managedForeignPtr . toManagedPtr $ w
+      liftIO $ putStrLn $ indent <> name <> "  " <> show ptr
+      maybeContainer <- liftIO $ castTo Container w
+      for_ maybeContainer $ \container -> do
+        children <- containerGetChildren container
+        for_ children $ \child -> do
+          go ("  " <> indent) child
