diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.9.3
+
+* Added `intercalate`, `splitWhen`, `splitElem`, and `splitSeq` [#80](https://github.com/snoyberg/mono-traversable/pull/80)
+
 ## 0.9.2.1
 
 * Tweak test suite for 32-bit systems [#78](https://github.com/snoyberg/mono-traversable/issues/78)
diff --git a/mono-traversable.cabal b/mono-traversable.cabal
--- a/mono-traversable.cabal
+++ b/mono-traversable.cabal
@@ -1,5 +1,5 @@
 name:                mono-traversable
-version:             0.9.2.1
+version:             0.9.3
 synopsis:            Type classes for mapping, folding, and traversing monomorphic containers
 description:         Monomorphic variants of the Functor, Foldable, and Traversable typeclasses. If you understand Haskell's basic typeclasses, you understand mono-traversable. In addition to what you are used to, it adds on an IsSequence typeclass and has code for marking data structures as non-empty.
 homepage:            https://github.com/snoyberg/mono-traversable
@@ -37,6 +37,7 @@
                      , vector-algorithms >= 0.6
                      , dlist >= 0.6 && < 1.0
                      , dlist-instances == 0.1.*
+                     , split >= 0.2
   hs-source-dirs:      src
   default-language:    Haskell2010
 
diff --git a/src/Data/MonoTraversable.hs b/src/Data/MonoTraversable.hs
--- a/src/Data/MonoTraversable.hs
+++ b/src/Data/MonoTraversable.hs
@@ -599,7 +599,6 @@
     unsafeLast = V.unsafeLast
     maximumByEx = V.maximumBy
     minimumByEx = V.minimumBy
-    {-# INLINE ofoldMap #-}
     {-# INLINE ofoldr #-}
     {-# INLINE ofoldl' #-}
     {-# INLINE otoList #-}
diff --git a/src/Data/Sequences.hs b/src/Data/Sequences.hs
--- a/src/Data/Sequences.hs
+++ b/src/Data/Sequences.hs
@@ -7,10 +7,11 @@
 module Data.Sequences where
 
 import Data.Maybe (fromJust, isJust)
-import Data.Monoid (Monoid, mconcat, mempty)
+import Data.Monoid (Monoid, mappend, mconcat, mempty)
 import Data.MonoTraversable
 import Data.Int (Int64, Int)
 import qualified Data.List as List
+import qualified Data.List.Split as List
 import qualified Control.Monad (filterM, replicateM)
 import Prelude (Bool (..), Monad (..), Maybe (..), Ordering (..), Ord (..), Eq (..), Functor (..), fromIntegral, otherwise, (-), fst, snd, Integral, ($), flip, maybe, error)
 import Data.Char (Char, isSpace)
@@ -60,8 +61,6 @@
     -- @
     intersperse :: Element seq -> seq -> seq
 
-    -- FIXME split :: (Element seq -> Bool) -> seq -> [seq]
-
     -- | Reverse a sequence
     --
     -- @
@@ -411,6 +410,23 @@
     unsafeIndex :: seq -> Index seq -> Element seq
     unsafeIndex = indexEx
 
+    -- | 'intercalate' @seq seqs@ inserts @seq@ in between @seqs@ and
+    -- concatenates the result.
+    --
+    -- Since 0.9.3
+    intercalate :: seq -> [seq] -> seq
+    intercalate = defaultIntercalate
+
+    -- | 'splitWhen' splits a sequence into components delimited by separators,
+    -- where the predicate returns True for a separator element. The resulting
+    -- components do not contain the separators. Two adjacent separators result
+    -- in an empty component in the output. The number of resulting components
+    -- is greater by one than number of separators.
+    --
+    -- Since 0.9.3
+    splitWhen :: (Element seq -> Bool) -> seq -> [seq]
+    splitWhen = defaultSplitWhen
+
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -440,6 +456,7 @@
     {-# INLINE index #-}
     {-# INLINE indexEx #-}
     {-# INLINE unsafeIndex #-}
+    {-# INLINE splitWhen #-}
 
 -- | Use "Data.List"'s implementation of 'Data.List.find'.
 defaultFind :: MonoFoldable seq => (Element seq -> Bool) -> seq -> Maybe (Element seq)
@@ -461,6 +478,17 @@
 defaultSortBy f = fromList . sortBy f . otoList
 {-# INLINE defaultSortBy #-}
 
+-- | Default 'intercalate'
+defaultIntercalate :: (IsSequence seq) => seq -> [seq] -> seq
+defaultIntercalate _ [] = mempty
+defaultIntercalate s (seq:seqs) = mconcat (seq : List.map (s `mappend`) seqs)
+{-# INLINE defaultIntercalate #-}
+
+-- | Use 'splitWhen' from "Data.List.Split"
+defaultSplitWhen :: IsSequence seq => (Element seq -> Bool) -> seq -> [seq]
+defaultSplitWhen f = List.map fromList . List.splitWhen f . otoList
+{-# INLINE defaultSplitWhen #-}
+
 -- | Sort a vector using an supplied element ordering function.
 vectorSortBy :: VG.Vector v e => (e -> e -> Ordering) -> v e -> v e
 vectorSortBy f = VG.modify (VAM.sortBy f)
@@ -538,6 +566,8 @@
       where
         (matches, nonMatches) = partition ((== f head) . f) tail
     groupAllOn _ [] = []
+    intercalate = List.intercalate
+    splitWhen = List.splitWhen
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -564,6 +594,8 @@
     {-# INLINE initEx #-}
     {-# INLINE unsafeTail #-}
     {-# INLINE unsafeInit #-}
+    {-# INLINE intercalate #-}
+    {-# INLINE splitWhen #-}
 
 instance SemiSequence (NE.NonEmpty a) where
     type Index (NE.NonEmpty a) = Int
@@ -618,6 +650,9 @@
     tailEx = S.tail
     initEx = S.init
     unsafeTail = SU.unsafeTail
+    splitWhen f s | S.null s = [S.empty]
+                  | otherwise = S.splitWith f s
+    intercalate = S.intercalate
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -644,6 +679,8 @@
     {-# INLINE initEx #-}
     {-# INLINE unsafeTail #-}
     {-# INLINE unsafeInit #-}
+    {-# INLINE splitWhen #-}
+    {-# INLINE intercalate #-}
 
     index bs i
         | i >= S.length bs = Nothing
@@ -688,6 +725,8 @@
     groupBy = T.groupBy
     tailEx = T.tail
     initEx = T.init
+    splitWhen = T.split
+    intercalate = T.intercalate
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -714,6 +753,8 @@
     {-# INLINE initEx #-}
     {-# INLINE unsafeTail #-}
     {-# INLINE unsafeInit #-}
+    {-# INLINE splitWhen #-}
+    {-# INLINE intercalate #-}
 
     index t i
         | i >= T.length t = Nothing
@@ -758,6 +799,9 @@
     groupBy = L.groupBy
     tailEx = L.tail
     initEx = L.init
+    splitWhen f s | L.null s = [L.empty]
+                  | otherwise = L.splitWith f s
+    intercalate = L.intercalate
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -784,6 +828,8 @@
     {-# INLINE initEx #-}
     {-# INLINE unsafeTail #-}
     {-# INLINE unsafeInit #-}
+    {-# INLINE splitWhen #-}
+    {-# INLINE intercalate #-}
 
     indexEx = L.index
     unsafeIndex = L.index
@@ -825,6 +871,8 @@
     groupBy = TL.groupBy
     tailEx = TL.tail
     initEx = TL.init
+    splitWhen = TL.split
+    intercalate = TL.intercalate
     {-# INLINE fromList #-}
     {-# INLINE break #-}
     {-# INLINE span #-}
@@ -851,6 +899,8 @@
     {-# INLINE initEx #-}
     {-# INLINE unsafeTail #-}
     {-# INLINE unsafeInit #-}
+    {-# INLINE splitWhen #-}
+    {-# INLINE intercalate #-}
 
     indexEx = TL.index
     unsafeIndex = TL.index
@@ -1198,6 +1248,42 @@
 
 -- | A typeclass for sequences whose elements have the 'Eq' typeclass
 class (MonoFoldableEq seq, IsSequence seq, Eq (Element seq)) => EqSequence seq where
+
+    -- | @'splitElem'@ splits a sequence into components delimited by separator
+    -- element. It's equivalent to 'splitWhen' with equality predicate:
+    --
+    -- > splitElem sep === splitWhen (== sep)
+    --
+    -- Since 0.9.3
+    splitElem :: Element seq -> seq -> [seq]
+    splitElem x = splitWhen (== x)
+
+    -- | @'splitSeq'@ splits a sequence into components delimited by
+    -- separator subsequence. 'splitSeq' is the right inverse of 'intercalate':
+    --
+    -- > intercalate x . splitSeq x === id
+    --
+    -- 'splitElem' can be considered a special case of 'splitSeq'
+    --
+    -- > splitSeq (singleton sep) === splitElem sep
+    --
+    -- @'splitSeq' mempty@ is another special case: it splits just before each
+    -- element, and in line with 'splitWhen' rules, it has at least one output
+    -- component:
+    --
+    -- @
+    -- > 'splitSeq' "" ""
+    -- [""]
+    -- > 'splitSeq' "" "a"
+    -- ["", "a"]
+    -- > 'splitSeq' "" "ab"
+    -- ["", "a", "b"]
+    -- @
+    --
+    -- Since 0.9.3
+    splitSeq :: seq -> seq -> [seq]
+    splitSeq = defaultSplitOn
+
     -- | 'stripPrefix' drops the given prefix from a sequence.
     -- It returns 'Nothing' if the sequence did not start with the prefix
     -- given, or 'Just' the sequence after the prefix, if it does.
@@ -1249,6 +1335,8 @@
     -- Equivalent to @'groupAllOn' id@
     groupAll :: seq -> [seq]
     groupAll = groupAllOn id
+    {-# INLINE splitElem #-}
+    {-# INLINE splitSeq #-}
     {-# INLINE isPrefixOf #-}
     {-# INLINE isSuffixOf #-}
     {-# INLINE isInfixOf #-}
@@ -1265,13 +1353,19 @@
 notElem :: EqSequence seq => Element seq -> seq -> Bool
 notElem = onotElem
 
+-- | Use 'splitOn' from "Data.List.Split"
+defaultSplitOn :: EqSequence s => s -> s -> [s]
+defaultSplitOn sep = List.map fromList . List.splitOn (otoList sep) . otoList
+
 instance Eq a => EqSequence [a] where
+    splitSeq = List.splitOn
     stripPrefix = List.stripPrefix
     stripSuffix x y = fmap reverse (List.stripPrefix (reverse x) (reverse y))
     group = List.group
     isPrefixOf = List.isPrefixOf
     isSuffixOf x y = List.isPrefixOf (List.reverse x) (List.reverse y)
     isInfixOf = List.isInfixOf
+    {-# INLINE splitSeq #-}
     {-# INLINE stripPrefix #-}
     {-# INLINE stripSuffix #-}
     {-# INLINE group #-}
@@ -1281,6 +1375,8 @@
     {-# INLINE isInfixOf #-}
 
 instance EqSequence S.ByteString where
+    splitElem sep s | S.null s = [S.empty]
+                    | otherwise = S.split sep s
     stripPrefix x y
         | x `S.isPrefixOf` y = Just (S.drop (S.length x) y)
         | otherwise = Nothing
@@ -1291,6 +1387,7 @@
     isPrefixOf = S.isPrefixOf
     isSuffixOf = S.isSuffixOf
     isInfixOf = S.isInfixOf
+    {-# INLINE splitElem #-}
     {-# INLINE stripPrefix #-}
     {-# INLINE stripSuffix #-}
     {-# INLINE group #-}
@@ -1300,6 +1397,8 @@
     {-# INLINE isInfixOf #-}
 
 instance EqSequence L.ByteString where
+    splitElem sep s | L.null s = [L.empty]
+                    | otherwise = L.split sep s
     stripPrefix x y
         | x `L.isPrefixOf` y = Just (L.drop (L.length x) y)
         | otherwise = Nothing
@@ -1310,6 +1409,7 @@
     isPrefixOf = L.isPrefixOf
     isSuffixOf = L.isSuffixOf
     isInfixOf x y = L.unpack x `List.isInfixOf` L.unpack y
+    {-# INLINE splitElem #-}
     {-# INLINE stripPrefix #-}
     {-# INLINE stripSuffix #-}
     {-# INLINE group #-}
@@ -1319,12 +1419,15 @@
     {-# INLINE isInfixOf #-}
 
 instance EqSequence T.Text where
+    splitSeq sep | T.null sep = (:) T.empty . List.map singleton . T.unpack
+                 | otherwise = T.splitOn sep
     stripPrefix = T.stripPrefix
     stripSuffix = T.stripSuffix
     group = T.group
     isPrefixOf = T.isPrefixOf
     isSuffixOf = T.isSuffixOf
     isInfixOf = T.isInfixOf
+    {-# INLINE splitSeq #-}
     {-# INLINE stripPrefix #-}
     {-# INLINE stripSuffix #-}
     {-# INLINE group #-}
@@ -1334,12 +1437,15 @@
     {-# INLINE isInfixOf #-}
 
 instance EqSequence TL.Text where
+    splitSeq sep | TL.null sep = (:) TL.empty . List.map singleton . TL.unpack
+                 | otherwise = TL.splitOn sep
     stripPrefix = TL.stripPrefix
     stripSuffix = TL.stripSuffix
     group = TL.group
     isPrefixOf = TL.isPrefixOf
     isSuffixOf = TL.isSuffixOf
     isInfixOf = TL.isInfixOf
+    {-# INLINE splitSeq #-}
     {-# INLINE stripPrefix #-}
     {-# INLINE stripSuffix #-}
     {-# INLINE group #-}
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,6 +1,8 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ViewPatterns #-}
+
 module Spec where
 
 import Data.MonoTraversable
@@ -9,11 +11,14 @@
 import qualified Data.Sequence as Seq
 import qualified Data.NonNull as NN
 import Data.ByteVector
+import Data.Monoid (mempty, mconcat)
+import Data.Maybe (fromMaybe)
 
 import Test.Hspec
 import Test.Hspec.QuickCheck
 import Test.HUnit ((@?=))
 import Test.QuickCheck hiding (NonEmptyList(..))
+import qualified Test.QuickCheck as QC
 import qualified Test.QuickCheck.Modifiers as QCM
 
 import Data.Text (Text)
@@ -38,7 +43,7 @@
 import Control.Monad.Trans.Writer
 
 import Prelude (Bool (..), ($), IO, min, abs, Eq (..), (&&), fromIntegral, Ord (..), String, mod, Int, Integer, show,
-                return, asTypeOf, (.), Show, id, (+), succ, Maybe (..), (*), mod, map, flip, otherwise, (-), div, seq)
+                return, asTypeOf, (.), Show, id, (+), succ, Maybe (..), (*), mod, map, flip, otherwise, (-), div, seq, maybe)
 import qualified Prelude
 
 instance Arbitrary a => Arbitrary (NE.NonEmpty a) where
@@ -385,6 +390,59 @@
         test "Strict Text" T.empty
         test "Lazy Text" TL.empty
 
+    describe "Intercalate" $ do
+        let test typ dummy = describe typ $ do
+                prop "intercalate === defaultIntercalate" $ \list lists ->
+                    let seq = fromListAs list dummy
+                        seqs = map (`fromListAs` dummy) lists
+                    in intercalate seq seqs @?= defaultIntercalate seq seqs
+        test "List" ([] :: [Int])
+        test "Vector" (V.empty :: V.Vector Int)
+        test "Storable Vector" (VS.empty :: VS.Vector Int)
+        test "Unboxed Vector" (U.empty :: U.Vector Int)
+        test "Strict ByteString" S.empty
+        test "Lazy ByteString" L.empty
+        test "Strict Text" T.empty
+        test "Lazy Text" TL.empty
+
+    describe "Splitting" $ do
+        let test typ dummy = describe typ $ do
+                let fromList' = (`fromListAs` dummy)
+                let fromSepList sep = fromList' . map (fromMaybe sep)
+                prop "intercalate sep . splitSeq sep === id" $
+                    \(fromList' -> sep) ->
+                    \(mconcat . map (maybe sep fromList') -> xs) ->
+                    intercalate sep (splitSeq sep xs) @?= xs
+                prop "splitSeq mempty xs === mempty : map singleton (otoList xs)" $
+                    \input ->
+                    splitSeq mempty (fromList' input) @?= mempty : map singleton input
+                prop "splitSeq _ mempty == [mempty]" $
+                    \(fromList' -> sep) ->
+                    splitSeq sep mempty @?= [mempty]
+                prop "intercalate (singleton sep) . splitElem sep === id" $
+                    \sep -> \(fromSepList sep -> xs) ->
+                    intercalate (singleton sep) (splitElem sep xs) @?= xs
+                prop "length . splitElem sep === succ . length . filter (== sep)" $
+                    \sep -> \(fromSepList sep -> xs) ->
+                    olength (splitElem sep xs) @?= olength (filter (== sep) xs) + 1
+                prop "splitElem sep (replicate n sep) == replicate (n+1) mempty" $
+                    \(NonNegative n) sep ->
+                    splitElem sep (fromList' (replicate n sep)) @?= replicate (n + 1) mempty
+                prop "splitElem sep === splitWhen (== sep)" $
+                    \sep -> \(fromSepList sep -> xs) ->
+                    splitElem sep xs @?= splitWhen (== sep) xs
+                prop "splitElem sep === splitSeq (singleton sep)" $
+                    \sep -> \(fromSepList sep -> xs) ->
+                    splitElem sep xs @?= splitSeq (singleton sep) xs
+        test "List" ([] :: [Int])
+        test "Vector" (V.empty :: V.Vector Int)
+        test "Storable Vector" (VS.empty :: VS.Vector Int)
+        test "Unboxed Vector" (U.empty :: U.Vector Int)
+        test "Strict ByteString" S.empty
+        test "Lazy ByteString" L.empty
+        test "Strict Text" T.empty
+        test "Lazy Text" TL.empty
+
     describe "Data.ByteVector" $ do
         prop "toByteVector" $ \ws ->
             (otoList . toByteVector . fromList $ ws) @?= ws
@@ -398,3 +456,4 @@
 
         it "#31 find doesn't infinitely loop on NonEmpty" $
             find (== "a") ("a" NE.:| ["d","fgf"]) @?= Just "a"
+
