diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Extra
 
+1.7.3, released 2020-05-30
+    #58, add disjointOrd and disjointOrdBy
 1.7.2, released 2020-05-25
     #56, add zipWithLongest
     #57, make duration in MonadIO
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.7.2
+version:            1.7.3
 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
@@ -28,7 +28,7 @@
     nubOn, groupOn,
     nubSort, nubSortBy, nubSortOn,
     maximumOn, minimumOn,
-    disjoint, allSame, anySame,
+    disjoint, disjointOrd, disjointOrdBy, allSame, anySame,
     repeatedly, firstJust,
     concatUnzip, concatUnzip3,
     zipFrom, zipWithFrom, zipWithLongest,
@@ -65,6 +65,33 @@
 -- > disjoint [1,2,3] [4,1] == False
 disjoint :: Eq a => [a] -> [a] -> Bool
 disjoint xs = null . intersect xs
+
+-- | /O((m+n) log m), m <= n/. Are two lists disjoint, with no elements in common.
+--
+-- @disjointOrd@ is more strict than `disjoint`. For example, @disjointOrd@ cannot
+-- terminate if both lists are inifite, while `disjoint` can.
+--
+-- > disjointOrd [1,2,3] [4,5] == True
+-- > disjointOrd [1,2,3] [4,1] == False
+disjointOrd :: Ord a => [a] -> [a] -> Bool
+disjointOrd = disjointOrdBy compare
+
+-- | A version of 'disjointOrd' with a custom predicate.
+--
+-- > disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,5] == True
+-- > disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,8] == False
+disjointOrdBy :: (a -> a -> Ordering) -> [a] -> [a] -> Bool
+disjointOrdBy cmp xs ys
+    | shorter xs ys = go xs ys
+    | otherwise = go ys xs
+  where
+    shorter _ [] = False
+    shorter [] _ = True
+    shorter (_:xs) (_:ys) = shorter xs ys
+
+    go xs = not . any (\a -> memberRB cmp a tree)
+      where
+        tree = foldl' (flip (insertRB cmp)) E xs
 
 -- | Is there any element which occurs more than once.
 --
diff --git a/src/Extra.hs b/src/Extra.hs
--- a/src/Extra.hs
+++ b/src/Extra.hs
@@ -23,7 +23,7 @@
     writeIORef', atomicWriteIORef', atomicModifyIORef_, atomicModifyIORef'_,
     -- * Data.List.Extra
     -- | Extra functions available in @"Data.List.Extra"@.
-    lower, upper, trim, trimStart, trimEnd, word1, line1, escapeHTML, escapeJSON, unescapeHTML, unescapeJSON, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, dropPrefix, dropSuffix, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, headDef, lastDef, notNull, list, unsnoc, cons, snoc, drop1, dropEnd1, mconcatMap, enumerate, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, nubSort, nubSortBy, nubSortOn, maximumOn, minimumOn, disjoint, allSame, anySame, repeatedly, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, zipWithLongest, replace, merge, mergeBy,
+    lower, upper, trim, trimStart, trimEnd, word1, line1, escapeHTML, escapeJSON, unescapeHTML, unescapeJSON, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, dropPrefix, dropSuffix, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, headDef, lastDef, notNull, list, unsnoc, cons, snoc, drop1, dropEnd1, mconcatMap, enumerate, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, nubSort, nubSortBy, nubSortOn, maximumOn, minimumOn, disjoint, disjointOrd, disjointOrdBy, allSame, anySame, repeatedly, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, zipWithLongest, replace, merge, mergeBy,
     -- * Data.List.NonEmpty.Extra
     -- | Extra functions available in @"Data.List.NonEmpty.Extra"@.
     (|:), (|>), appendl, appendr, maximum1, minimum1, maximumBy1, minimumBy1, maximumOn1, minimumOn1,
diff --git a/test/TestGen.hs b/test/TestGen.hs
--- a/test/TestGen.hs
+++ b/test/TestGen.hs
@@ -81,6 +81,10 @@
     testGen "\\xs -> repeatedly line1 xs == lines xs" $ \xs -> repeatedly line1 xs == lines xs
     testGen "disjoint [1,2,3] [4,5] == True" $ disjoint [1,2,3] [4,5] == True
     testGen "disjoint [1,2,3] [4,1] == False" $ disjoint [1,2,3] [4,1] == False
+    testGen "disjointOrd [1,2,3] [4,5] == True" $ disjointOrd [1,2,3] [4,5] == True
+    testGen "disjointOrd [1,2,3] [4,1] == False" $ disjointOrd [1,2,3] [4,1] == False
+    testGen "disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,5] == True" $ disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,5] == True
+    testGen "disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,8] == False" $ disjointOrdBy (compare `on` (`mod` 7)) [1,2,3] [4,8] == False
     testGen "anySame [1,1,2] == True" $ anySame [1,1,2] == True
     testGen "anySame [1,2,3] == False" $ anySame [1,2,3] == False
     testGen "anySame (1:2:1:undefined) == True" $ anySame (1:2:1:undefined) == True
