diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+1.5.23
+
+* Add `fromIO` utility
+* Build against GHC 9.0 / 9.2
+
 1.5.22
 
 * Add new `update` utility
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -2,7 +2,7 @@
 module Main where
 
 import qualified Data.Text as Text
-import Criterion.Main
+import Test.Tasty.Bench
 import Turtle
 
 boundedNaive :: Int -> Int -> Pattern a -> Pattern [a]
diff --git a/src/Turtle/Shell.hs b/src/Turtle/Shell.hs
--- a/src/Turtle/Shell.hs
+++ b/src/Turtle/Shell.hs
@@ -75,6 +75,7 @@
     , select
     , liftIO
     , using
+    , fromIO
     ) where
 
 import Control.Applicative
@@ -245,3 +246,20 @@
             x' <- step x a
             k $! x'
     Data.Foldable.foldr step' done as $! begin )
+
+-- | Convert an `IO` action that returns a `Maybe` into a `Shell`
+fromIO :: IO (Maybe a) -> Shell a
+fromIO io =
+    Shell
+        (\(FoldShell step begin done) -> do
+            let loop x = do
+                    m <- io
+                    case m of
+                        Just a -> do
+                            x' <- step x a
+                            loop x'
+                        Nothing -> do
+                            done x
+
+            loop begin
+        )
diff --git a/turtle.cabal b/turtle.cabal
--- a/turtle.cabal
+++ b/turtle.cabal
@@ -1,5 +1,5 @@
 Name: turtle
-Version: 1.5.22
+Version: 1.5.23
 Cabal-Version: >=1.10
 Build-Type: Simple
 License: BSD3
@@ -39,8 +39,20 @@
     then you should also check out the @Shelly@ library which provides similar
     functionality.
 Category: System
+
+Tested-With:
+  GHC == 9.2.1
+  GHC == 9.0.1
+  GHC == 8.10.7
+  GHC == 8.8.4
+  GHC == 8.6.5
+  GHC == 8.4.4
+  GHC == 8.2.2
+  GHC == 8.0.2
+
 Extra-Source-Files:
     CHANGELOG.md
+
 Source-Repository head
     Type: git
     Location: https://github.com/Gabriel439/Haskell-Turtle-Library
@@ -48,10 +60,11 @@
 Library
     HS-Source-Dirs: src
     Build-Depends:
-        base                 >= 4.6     && < 5   ,
+        -- 2021-09-07: Turtle.Prelude uses GHC-8.0 features, so base >= 4.9
+        base                 >= 4.9     && < 5   ,
         ansi-wl-pprint       >= 0.6     && < 0.7 ,
         async                >= 2.0.0.0 && < 2.3 ,
-        bytestring           >= 0.9.1.8 && < 0.11,
+        bytestring           >= 0.9.1.8 && < 0.12,
         clock                >= 0.4.1.2 && < 0.9 ,
         containers           >= 0.5.0.0 && < 0.7 ,
         directory            >= 1.3.1.0 && < 1.4 ,
@@ -66,8 +79,8 @@
         streaming-commons                  < 0.3 ,
         temporary                          < 1.4 ,
         text                 >= 1.0.0   && < 1.3 ,
-        time                               < 1.10,
-        transformers         >= 0.2.0.0 && < 0.6 ,
+        time                               < 1.13,
+        transformers         >= 0.2.0.0 && < 0.7 ,
         optparse-applicative >= 0.16    && < 0.17,
         optional-args        >= 1.0     && < 2.0 ,
         unix-compat          >= 0.4     && < 0.6
@@ -75,9 +88,7 @@
         Build-Depends: Win32 >= 2.2.0.1 && < 2.9
     else
         Build-Depends: unix  >= 2.5.1.0 && < 2.8
-    if !impl(ghc >= 8.0)
-        Build-Depends: fail        >= 4.9.0.0 && < 4.10,
-                       semigroups  >= 0.5.0   && < 0.20
+
     Exposed-Modules:
         Turtle,
         Turtle.Bytes,
@@ -134,8 +145,6 @@
         temporary,
         system-filepath >= 0.4,
         turtle
-    if !impl(ghc >= 8.0)
-        Build-Depends: fail
 
 benchmark bench
     Type: exitcode-stdio-1.0
@@ -144,10 +153,7 @@
     GHC-Options: -O2 -Wall -threaded
     Default-Language: Haskell2010
     Build-Depends:
-        base      >= 4   && < 5  ,
-        text                < 1.3,
+        base        >= 4     && < 5  ,
+        tasty-bench >= 0.3.1         ,
+        text                    < 1.3,
         turtle
-    if impl(ghc < 7.8)
-        Build-Depends: criterion >= 0.4 && < 1.1.4.0
-    else
-        Build-Depends: criterion >= 0.4 && < 1.6
