diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Extra
 
+1.4
+    Add stripInfix and stripInfixEnd
 1.3.1
     #9, support directory-1.2.3
 1.3
diff --git a/extra.cabal b/extra.cabal
--- a/extra.cabal
+++ b/extra.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.10
 build-type:         Simple
 name:               extra
-version:            1.3.1
+version:            1.4
 license:            BSD3
 license-file:       LICENSE
 category:           Development
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
@@ -11,7 +11,8 @@
     lower, upper, trim, trimStart, trimEnd, word1,
     -- * Splitting    
     dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd,
-    dropWhileEnd, dropWhileEnd', takeWhileEnd, stripSuffix,
+    dropWhileEnd, dropWhileEnd', takeWhileEnd,
+    stripSuffix, stripInfix, stripInfixEnd,
     wordsBy, linesBy,
     breakOn, breakOnEnd, splitOn, split, chunksOf,
     -- * Basics
@@ -26,11 +27,13 @@
     replace, merge, mergeBy,
     ) where
 
+import Control.Applicative
 import Data.List
 import Data.Maybe
 import Data.Function
 import Data.Char
 import Data.Tuple.Extra
+import Prelude
 
 
 -- | Apply some operation repeatedly, producing an element of output
@@ -382,6 +385,7 @@
 -- The first element of the returned tuple
 -- is the prefix of @haystack@ before @needle@ is matched.  The second
 -- is the remainder of @haystack@, starting with the match.
+-- If you want the remainder /without/ the patch, use 'stripInfix'.
 --
 -- > breakOn "::" "a::b::c" == ("a", "::b::c")
 -- > breakOn "/" "foobar"   == ("foobar", "")
@@ -400,7 +404,7 @@
 --
 -- > breakOnEnd "::" "a::b::c" == ("a::b::", "c")
 breakOnEnd :: Eq a => [a] -> [a] -> ([a], [a])
-breakOnEnd needle haystack = (reverse *** reverse) $ swap $ breakOn (reverse needle) (reverse haystack)
+breakOnEnd needle haystack = both reverse $ swap $ breakOn (reverse needle) (reverse haystack)
 
 
 -- | Break a list into pieces separated by the first
@@ -467,6 +471,27 @@
 -- > stripSuffix "foo" "quux"   == Nothing
 stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]
 stripSuffix a b = fmap reverse $ stripPrefix (reverse a) (reverse b)
+
+
+-- | Return the the string before and after the search string,
+--   or 'Nothing' if the search string is not present.
+--
+-- Examples:
+--
+-- > stripInfix "::" "a::b::c" == Just ("a", "b::c")
+-- > stripInfix "/" "foobar"   == Nothing
+stripInfix :: Eq a => [a] -> [a] -> Maybe ([a], [a])
+stripInfix needle haystack | Just rest <- stripPrefix needle haystack = Just ([], rest)
+stripInfix needle [] = Nothing
+stripInfix needle (x:xs) = first (x:) <$> stripInfix needle xs
+
+
+-- | Similar to 'stripInfix', but searches from the end of the
+-- string.
+--
+-- > stripInfixEnd "::" "a::b::c" == Just ("a::b", "c")
+stripInfixEnd :: Eq a => [a] -> [a] -> Maybe ([a], [a])
+stripInfixEnd needle haystack = both reverse . swap <$> stripInfix (reverse needle) (reverse haystack)
 
 
 -- | Split a list into chunks of a given size. The last chunk may contain
diff --git a/src/Extra.hs b/src/Extra.hs
--- a/src/Extra.hs
+++ b/src/Extra.hs
@@ -20,7 +20,7 @@
     modifyIORef', writeIORef', atomicModifyIORef', atomicWriteIORef, atomicWriteIORef',
     -- * Data.List.Extra
     -- | Extra functions available in @"Data.List.Extra"@.
-    lower, upper, trim, trimStart, trimEnd, word1, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd, dropWhileEnd', takeWhileEnd, stripSuffix, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, list, uncons, unsnoc, cons, snoc, drop1, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, sortOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, replace, merge, mergeBy,
+    lower, upper, trim, trimStart, trimEnd, word1, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, list, uncons, unsnoc, cons, snoc, drop1, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, sortOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, replace, merge, mergeBy,
     -- * Data.Tuple.Extra
     -- | Extra functions available in @"Data.Tuple.Extra"@.
     first, second, (***), (&&&), dupe, both, fst3, snd3, thd3,
diff --git a/test/TestGen.hs b/test/TestGen.hs
--- a/test/TestGen.hs
+++ b/test/TestGen.hs
@@ -165,6 +165,9 @@
     testGen "stripSuffix \"bar\" \"foobar\" == Just \"foo\"" $ stripSuffix "bar" "foobar" == Just "foo"
     testGen "stripSuffix \"\"    \"baz\"    == Just \"baz\"" $ stripSuffix ""    "baz"    == Just "baz"
     testGen "stripSuffix \"foo\" \"quux\"   == Nothing" $ stripSuffix "foo" "quux"   == Nothing
+    testGen "stripInfix \"::\" \"a::b::c\" == Just (\"a\", \"b::c\")" $ stripInfix "::" "a::b::c" == Just ("a", "b::c")
+    testGen "stripInfix \"/\" \"foobar\"   == Nothing" $ stripInfix "/" "foobar"   == Nothing
+    testGen "stripInfixEnd \"::\" \"a::b::c\" == Just (\"a::b\", \"c\")" $ stripInfixEnd "::" "a::b::c" == Just ("a::b", "c")
     testGen "chunksOf 3 \"my test\" == [\"my \",\"tes\",\"t\"]" $ chunksOf 3 "my test" == ["my ","tes","t"]
     testGen "chunksOf 3 \"mytest\"  == [\"myt\",\"est\"]" $ chunksOf 3 "mytest"  == ["myt","est"]
     testGen "chunksOf 8 \"\"        == []" $ chunksOf 8 ""        == []
