diff --git a/atomic-modify.cabal b/atomic-modify.cabal
--- a/atomic-modify.cabal
+++ b/atomic-modify.cabal
@@ -1,14 +1,16 @@
--- This file has been generated from package.yaml by hpack version 0.17.0.
+-- This file has been generated from package.yaml by hpack version 0.20.0.
 --
 -- see: https://github.com/sol/hpack
+--
+-- hash: b47558f51afd9007c96683e4f3ac5b24a8d05dcb4a8ab911849c4a7f9fbdbd57
 
 name:           atomic-modify
-version:        0.1.0.0
+version:        0.1.0.1
 synopsis:       A typeclass for mutable references that have an atomic modify operation.
 
 description:    A typeclass for mutable references that have an atomic modify operation. Generalizes atomic modify operations in IO and STM contexts for IORef, MVar, TVar, and TMVar.
 category:       Concurrency
-homepage:       https://github.com/chris-martin/haskell-libraries
+homepage:       https://github.com/chris-martin/atomic-modify
 author:         Chris Martin <ch.martin@gmail.com>
 maintainer:     Chris Martin <ch.martin@gmail.com>
 license:        Apache-2.0
@@ -22,7 +24,7 @@
   default-extensions: NoImplicitPrelude
   ghc-options: -Wall
   build-depends:
-      base >= 4.9 && < 4.10
+      base >=4.9 && <4.11
     , stm
   exposed-modules:
       Control.Concurrent.AtomicModify
diff --git a/src/Control/Concurrent/AtomicModify.hs b/src/Control/Concurrent/AtomicModify.hs
--- a/src/Control/Concurrent/AtomicModify.hs
+++ b/src/Control/Concurrent/AtomicModify.hs
@@ -9,21 +9,30 @@
 
 -}
 
-{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE BangPatterns, MultiParamTypeClasses #-}
 
 module Control.Concurrent.AtomicModify
-    ( AtomicModify (..)
-    , atomicModifyStrict_
-    , atomicModifyLazy_
-    ) where
+  ( AtomicModify (..)
+  , atomicModifyStrict_
+  , atomicModifyLazy_
+  ) where
 
 import Control.Concurrent.MVar (MVar, modifyMVar)
 import Control.Concurrent.STM (STM, TMVar, TVar, atomically, putTMVar, readTVar,
                                takeTMVar, writeTVar)
+import Control.Monad ((>>=))
+import Data.Function (($), (&))
+import Data.Functor (($>))
 import Data.IORef (IORef, atomicModifyIORef, atomicModifyIORef')
-import Prelude (IO, pure, ($), ($!))
+import Prelude (IO, pure, ($!))
 
+
+--------------------------------------------------------------------------------
+--  Class
+--------------------------------------------------------------------------------
+
 {- |
+
 A typeclass for mutable references that have an atomic modify operation.
 
 Type variables:
@@ -34,29 +43,51 @@
 As the name "atomic" implies, these functions are useful for using mutable
 references in a safe way to prevent race conditions in a multithreaded
 program.
+
 -}
 class AtomicModify ref m where
 
-    -- | Atomically modify the contents of a @ref@ (type @a@) and produce a
-    -- value (type @b@). This is strict; it forces the value stored in the @ref@
-    -- as well as the value returned.
-    atomicModifyStrict :: ref a -> (a -> (a, b)) -> m b
+  {- |
 
-    -- | Atomically modify the contents of a @ref@ (type @a@) and produce a
-    -- value (type @b@). This is lazy, which means if the program calls
-    -- 'atomicModifyLazy' many times, but seldomly uses the value, thunks will
-    -- pile up in memory resulting in a space leak.
-    atomicModifyLazy :: ref a -> (a -> (a, b)) -> m b
+  Atomically modify the contents of a @ref@ (type @a@) and produce a value (type
+  @b@). This is strict; it forces the value stored in the @ref@ as well as the
+  value returned.
 
--- | Atomically modify the contents of a @ref@. This is strict; it forces the
--- value stored in the @ref@ as well as the value returned.
+  -}
+  atomicModifyStrict :: ref a -> (a -> (a, b)) -> m b
+
+  {- |
+
+  Atomically modify the contents of a @ref@ (type @a@) and produce a value (type
+  @b@). This is lazy, which means if the program calls 'atomicModifyLazy' many
+  times, but seldomly uses the value, thunks will pile up in memory resulting in
+  a space leak.
+
+  -}
+  atomicModifyLazy :: ref a -> (a -> (a, b)) -> m b
+
+
+--------------------------------------------------------------------------------
+--  Functions
+--------------------------------------------------------------------------------
+
+{- |
+
+Atomically modify the contents of a @ref@. This is strict; it forces the value
+stored in the @ref@ as well as the value returned.
+
+-}
 atomicModifyStrict_ :: AtomicModify v m => v a -> (a -> a) -> m ()
 atomicModifyStrict_ ref f = atomicModifyStrict ref (\a -> (f a, ()))
 
--- | Atomically modify the contents of a @ref@ (type @a@) and produce a value
--- (type @b@). This is lazy, which means if the program calls
--- 'atomicModifyLazy_' many times, but seldomly uses the value, thunks will pile
--- up in memory resulting in a space leak.
+{- |
+
+Atomically modify the contents of a @ref@ (type @a@) and produce a value (type
+@b@). This is lazy, which means if the program calls 'atomicModifyLazy_' many
+times, but seldomly uses the value, thunks will pile up in memory resulting in a
+space leak.
+
+-}
 atomicModifyLazy_ :: AtomicModify v m => v a -> (a -> a) -> m ()
 atomicModifyLazy_ ref f = atomicModifyLazy ref (\a -> (f a, ()))
 
@@ -65,46 +96,36 @@
 --  Instances
 --------------------------------------------------------------------------------
 
-instance AtomicModify IORef IO where
+instance AtomicModify IORef IO
+  where
     atomicModifyLazy   ref f = atomicModifyIORef  ref f
     atomicModifyStrict ref f = atomicModifyIORef' ref f
 
-instance AtomicModify MVar IO where
+instance AtomicModify MVar IO
+  where
     atomicModifyLazy   ref f = modifyMVar ref (\x -> pure $  f x)
     atomicModifyStrict ref f = modifyMVar ref (\x -> pure $! f x)
 
-instance AtomicModify TVar STM where
-
-    atomicModifyLazy ref f = do
-        a <- readTVar ref
-        let (a', b) = f a
-        writeTVar ref a'
-        pure b
-
-    atomicModifyStrict ref f = do
-        a <- readTVar ref
-        let (a', b) = f a
-        writeTVar ref $! a'
-        pure $! b
-
-instance AtomicModify TMVar STM where
-
-    atomicModifyLazy ref f = do
-        a <- takeTMVar ref
-        let (a', b) = f a
-        putTMVar ref a'
-        pure b
+instance AtomicModify TVar STM
+  where
+    atomicModifyLazy ref f =
+      readTVar ref >>= \a -> f a & \( a',  b) -> writeTVar ref a' $> b
+    atomicModifyStrict ref f =
+      readTVar ref >>= \a -> f a & \(!a', !b) -> writeTVar ref a' $> b
 
-    atomicModifyStrict ref f = do
-        a <- takeTMVar ref
-        let (a', b) = f a
-        putTMVar ref $! a'
-        pure $! b
+instance AtomicModify TMVar STM
+  where
+    atomicModifyLazy ref f =
+      takeTMVar ref >>= \a -> f a & \( a',  b) -> putTMVar ref a' $> b
+    atomicModifyStrict ref f =
+      takeTMVar ref >>= \a -> f a & \(!a', !b) -> putTMVar ref a' $> b
 
-instance AtomicModify TVar IO where
+instance AtomicModify TVar IO
+  where
     atomicModifyLazy   ref f = atomically (atomicModifyLazy   ref f)
     atomicModifyStrict ref f = atomically (atomicModifyStrict ref f)
 
-instance AtomicModify TMVar IO where
+instance AtomicModify TMVar IO
+  where
     atomicModifyLazy   ref f = atomically (atomicModifyLazy   ref f)
     atomicModifyStrict ref f = atomically (atomicModifyStrict ref f)
