diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Extra
 
+1.6.20, released 2020-02-16
+    Add firstM, secondM
 1.6.19, released 2020-02-11
     #50, add headDef, lastDef, and dropEnd1
 1.6.18, released 2019-08-21
diff --git a/extra.cabal b/extra.cabal
--- a/extra.cabal
+++ b/extra.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.18
 build-type:         Simple
 name:               extra
-version:            1.6.19
+version:            1.6.20
 license:            BSD3
 license-file:       LICENSE
 category:           Development
diff --git a/src/Control/Concurrent/Extra.hs b/src/Control/Concurrent/Extra.hs
--- a/src/Control/Concurrent/Extra.hs
+++ b/src/Control/Concurrent/Extra.hs
@@ -76,7 +76,7 @@
 onceFork act = do
     bar <- newBarrier
     forkFinally act $ signalBarrier bar
-    return $ either throwIO return =<< waitBarrier bar
+    return $ eitherM throwIO return $ waitBarrier bar
 
 
 ---------------------------------------------------------------------
diff --git a/src/Control/Monad/Extra.hs b/src/Control/Monad/Extra.hs
--- a/src/Control/Monad/Extra.hs
+++ b/src/Control/Monad/Extra.hs
@@ -38,7 +38,7 @@
 -- | Like 'whenJust', but where the test can be monadic.
 whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()
 -- Can't reuse whenMaybe on GHC 7.8 or lower because Monad does not imply Applicative
-whenJustM mg f = maybe (return ()) f =<< mg
+whenJustM mg f = maybeM (return ()) f mg
 
 
 -- | Like 'when', but return either 'Nothing' if the predicate was 'False',
@@ -72,7 +72,7 @@
 
 -- | Monadic generalisation of 'fromMaybe'.
 fromMaybeM :: Monad m => m a -> m (Maybe a) -> m a
-fromMaybeM n x = maybe n pure =<< x
+fromMaybeM n x = maybeM n pure x
 
 
 -- | Monadic generalisation of 'either'.
@@ -204,7 +204,7 @@
 -- > anyM Just [False,False,undefined] == undefined
 -- > \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs)
 anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
-anyM p = foldr (\x -> ifM (p x) (return True)) (return False)
+anyM p = foldr ((||^) . p) (return False)
 
 -- | A version of 'all' lifted to a monad. Retains the short-circuiting behaviour.
 --
@@ -212,8 +212,7 @@
 -- > allM Just [True,True ,undefined] == undefined
 -- > \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs)
 allM :: Monad m => (a -> m Bool) -> [a] -> m Bool
-allM p [] = return True
-allM p (x:xs) = ifM (p x) (allM p xs) (return False)
+allM p = foldr ((&&^) . p) (return True)
 
 -- | A version of 'or' lifted to a monad. Retains the short-circuiting behaviour.
 --
@@ -244,4 +243,4 @@
 -- | Like 'findM', but also allows you to compute some additional information in the predicate.
 firstJustM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b)
 firstJustM p [] = return Nothing
-firstJustM p (x:xs) = maybe (firstJustM p xs) (return . Just) =<< p x
+firstJustM p (x:xs) = maybeM (firstJustM p xs) (return . Just) (p x)
diff --git a/src/Data/List/Extra.hs b/src/Data/List/Extra.hs
--- a/src/Data/List/Extra.hs
+++ b/src/Data/List/Extra.hs
@@ -289,7 +289,7 @@
 -- > \s -> fst (word1 s) == concat (take 1 $ words s)
 -- > \s -> words (snd $ word1 s) == drop 1 (words s)
 word1 :: String -> (String, String)
-word1 = second (dropWhile isSpace) . break isSpace . dropWhile isSpace
+word1 = second trimStart . break isSpace . trimStart
 
 -- | Split the first line off a string.
 --
diff --git a/src/Data/Tuple/Extra.hs b/src/Data/Tuple/Extra.hs
--- a/src/Data/Tuple/Extra.hs
+++ b/src/Data/Tuple/Extra.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TupleSections #-}
 
 -- | Extra functions for working with pairs and triples.
 --   Some of these functions are available in the "Control.Arrow" module,
@@ -8,6 +9,8 @@
     first, second, (***), (&&&),
     -- * More pair operations
     dupe, both,
+    -- * Monadic versions
+    firstM, secondM,
     -- * Operations on triple
     fst3, snd3, thd3,
     curry3, uncurry3
@@ -29,6 +32,18 @@
 -- > second reverse (1,"test") == (1,"tset")
 second :: (b -> b') -> (a, b) -> (a, b')
 second = Arrow.second
+
+-- | Update the first component of a pair.
+--
+-- > firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")]
+firstM :: Functor m => (a -> m a') -> (a, b) -> m (a', b)
+firstM f (a,b) = (,b) <$> f a
+
+-- | Update the second component of a pair.
+--
+-- > secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")]
+secondM :: Functor m => (b -> m b') -> (a, b) -> m (a, b')
+secondM f (a,b) = (a,) <$> f b
 
 -- | Given two functions, apply one to the first component and one to the second.
 --   A specialised version of 'Control.Arrow.***'.
diff --git a/src/Extra.hs b/src/Extra.hs
--- a/src/Extra.hs
+++ b/src/Extra.hs
@@ -29,7 +29,7 @@
     (|:), (|>), appendl, appendr, maximum1, minimum1, maximumBy1, minimumBy1, maximumOn1, minimumOn1,
     -- * Data.Tuple.Extra
     -- | Extra functions available in @"Data.Tuple.Extra"@.
-    first, second, (***), (&&&), dupe, both, fst3, snd3, thd3, curry3, uncurry3,
+    first, second, (***), (&&&), dupe, both, firstM, secondM, fst3, snd3, thd3, curry3, uncurry3,
     -- * Data.Version.Extra
     -- | Extra functions available in @"Data.Version.Extra"@.
     readVersion,
diff --git a/test/TestGen.hs b/test/TestGen.hs
--- a/test/TestGen.hs
+++ b/test/TestGen.hs
@@ -245,6 +245,8 @@
     testGen "(1 :| [3, 5, 3]) `union` (4 :| [5, 3, 5, 2]) == 1 :| [3, 5, 3, 4, 2]" $ (1 :| [3, 5, 3]) `union` (4 :| [5, 3, 5, 2]) == 1 :| [3, 5, 3, 4, 2]
     testGen "first succ (1,\"test\") == (2,\"test\")" $ first succ (1,"test") == (2,"test")
     testGen "second reverse (1,\"test\") == (1,\"tset\")" $ second reverse (1,"test") == (1,"tset")
+    testGen "firstM (\\x -> [x-1, x+1]) (1,\"test\") == [(0,\"test\"),(2,\"test\")]" $ firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")]
+    testGen "secondM (\\x -> [reverse x, x]) (1,\"test\") == [(1,\"tset\"),(1,\"test\")]" $ secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")]
     testGen "(succ *** reverse) (1,\"test\") == (2,\"tset\")" $ (succ *** reverse) (1,"test") == (2,"tset")
     testGen "(succ &&& pred) 1 == (2,0)" $ (succ &&& pred) 1 == (2,0)
     testGen "dupe 12 == (12, 12)" $ dupe 12 == (12, 12)
