diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,8 @@
 # Changelog for closed-intervals
 
+- 0.1.1.0 added properOverlap, splitIntersecting and splitProperlyIntersecting.
+  Added maybeBounds to the IntersectionQuery class.
+
 - 0.1.0.1 bugfix in hullSeqNonOverlap which was not caught 
   because the QuickCheck generator generated data which 
   did not meet the assumptions made by hullSeqNonOverlap.
diff --git a/closed-intervals.cabal b/closed-intervals.cabal
--- a/closed-intervals.cabal
+++ b/closed-intervals.cabal
@@ -1,7 +1,7 @@
 cabal-version: 1.12
 
 name:           closed-intervals
-version:        0.1.0.1
+version:        0.1.1.0
 synopsis:       Closed intervals of totally ordered types
 description:    see README.md
 author:         Olaf Klinke, Henning Thielemann
diff --git a/doctest/Test/Data/Interval.hs b/doctest/Test/Data/Interval.hs
--- a/doctest/Test/Data/Interval.hs
+++ b/doctest/Test/Data/Interval.hs
@@ -1,5 +1,5 @@
 -- Do not edit! Automatically created with doctest-extract from src/Data/Interval.hs
-{-# LINE 99 "src/Data/Interval.hs" #-}
+{-# LINE 107 "src/Data/Interval.hs" #-}
 
 module Test.Data.Interval where
 
@@ -7,7 +7,7 @@
 import Test.DocTest.Base
 import qualified Test.DocTest.Driver as DocTest
 
-{-# LINE 100 "src/Data/Interval.hs" #-}
+{-# LINE 108 "src/Data/Interval.hs" #-}
 import     Data.IntervalTest
 import     qualified Data.Sequence as Seq
 import     qualified Data.List as List
@@ -20,223 +20,260 @@
 
 test :: DocTest.T ()
 test = do
- DocTest.printPrefix "Data.Interval:177: "
-{-# LINE 177 "src/Data/Interval.hs" #-}
- DocTest.property
-{-# LINE 177 "src/Data/Interval.hs" #-}
-        (genInterval /\ \i -> overlapTime i i == intervalDuration i)
- DocTest.printPrefix "Data.Interval:178: "
-{-# LINE 178 "src/Data/Interval.hs" #-}
- DocTest.property
-{-# LINE 178 "src/Data/Interval.hs" #-}
-        (genInterval /\* \i j -> not (i `properlyIntersects` j) ==> overlapTime i j == 0)
- DocTest.printPrefix "Data.Interval:179: "
-{-# LINE 179 "src/Data/Interval.hs" #-}
- DocTest.property
-{-# LINE 179 "src/Data/Interval.hs" #-}
-        (genInterval /\* \i j -> overlapTime i j == (sum $ fmap intervalDuration $ maybeIntersection i j))
  DocTest.printPrefix "Data.Interval:189: "
 {-# LINE 189 "src/Data/Interval.hs" #-}
  DocTest.property
 {-# LINE 189 "src/Data/Interval.hs" #-}
-        (genInterval /\ \i c -> prevailing i (Seq.singleton (c,i)) == Just (c::Char))
+        (genInterval /\ \i -> overlapTime i i == intervalDuration i)
  DocTest.printPrefix "Data.Interval:190: "
 {-# LINE 190 "src/Data/Interval.hs" #-}
  DocTest.property
 {-# LINE 190 "src/Data/Interval.hs" #-}
-        (genInterval /\ \i -> genLabeledSeq /\ \js -> isJust (prevailing i js) == any (intersects i . snd) js)
+        (genInterval /\* \i j -> not (i `properlyIntersects` j) ==> overlapTime i j == 0)
  DocTest.printPrefix "Data.Interval:191: "
 {-# LINE 191 "src/Data/Interval.hs" #-}
  DocTest.property
 {-# LINE 191 "src/Data/Interval.hs" #-}
+        (genInterval /\* \i j -> overlapTime i j == (sum $ fmap intervalDuration $ maybeIntersection i j))
+ DocTest.printPrefix "Data.Interval:201: "
+{-# LINE 201 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 201 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i c -> prevailing i (Seq.singleton (c,i)) == Just (c::Char))
+ DocTest.printPrefix "Data.Interval:202: "
+{-# LINE 202 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 202 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i -> genLabeledSeq /\ \js -> isJust (prevailing i js) == any (intersects i . snd) js)
+ DocTest.printPrefix "Data.Interval:203: "
+{-# LINE 203 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 203 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genLabeledSeq /\* \js ks -> all (flip elem $ catMaybes [prevailing i js, prevailing i ks]) $ prevailing i (js<>ks))
- DocTest.printPrefix "Data.Interval:214: "
-{-# LINE 214 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:226: "
+{-# LINE 226 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 214 "src/Data/Interval.hs" #-}
+{-# LINE 226 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> isJust (maybeUnion i j) ==> fromJust (maybeUnion i j) `contains` i && fromJust (maybeUnion i j) `contains` j)
- DocTest.printPrefix "Data.Interval:215: "
-{-# LINE 215 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:227: "
+{-# LINE 227 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 215 "src/Data/Interval.hs" #-}
+{-# LINE 227 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> i `intersects` j ==> (maybeUnion i j >>= maybeIntersection i) == Just i)
- DocTest.printPrefix "Data.Interval:223: "
-{-# LINE 223 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:235: "
+{-# LINE 235 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 223 "src/Data/Interval.hs" #-}
+{-# LINE 235 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> i `intersects` j ==> i `contains` fromJust (maybeIntersection i j))
- DocTest.printPrefix "Data.Interval:231: "
-{-# LINE 231 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:243: "
+{-# LINE 243 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 231 "src/Data/Interval.hs" #-}
+{-# LINE 243 "src/Data/Interval.hs" #-}
         (\xs -> isJust (hull xs) ==> all (\x -> fromJust (hull xs) `contains` x) (xs :: [(Int,Int)]))
- DocTest.printPrefix "Data.Interval:248: "
-{-# LINE 248 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:260: "
+{-# LINE 260 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 248 "src/Data/Interval.hs" #-}
+{-# LINE 260 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> length (i `without` j) <= 2)
- DocTest.printPrefix "Data.Interval:249: "
-{-# LINE 249 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:261: "
+{-# LINE 261 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 249 "src/Data/Interval.hs" #-}
+{-# LINE 261 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> i `without` i == [])
- DocTest.printPrefix "Data.Interval:250: "
-{-# LINE 250 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:262: "
+{-# LINE 262 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 250 "src/Data/Interval.hs" #-}
+{-# LINE 262 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> all (contains i) (i `without` j))
- DocTest.printPrefix "Data.Interval:251: "
-{-# LINE 251 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:263: "
+{-# LINE 263 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 251 "src/Data/Interval.hs" #-}
+{-# LINE 263 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> not $ any (properlyIntersects j) (i `without` j))
- DocTest.printPrefix "Data.Interval:239: "
-{-# LINE 239 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:251: "
+{-# LINE 251 "src/Data/Interval.hs" #-}
  DocTest.example
-{-# LINE 239 "src/Data/Interval.hs" #-}
+{-# LINE 251 "src/Data/Interval.hs" #-}
       (without' (1,5) (4,5))
   [ExpectedLine [LineChunk "[(1,4)]"]]
- DocTest.printPrefix "Data.Interval:241: "
-{-# LINE 241 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:253: "
+{-# LINE 253 "src/Data/Interval.hs" #-}
  DocTest.example
-{-# LINE 241 "src/Data/Interval.hs" #-}
+{-# LINE 253 "src/Data/Interval.hs" #-}
       (without' (1,5) (2,3))
   [ExpectedLine [LineChunk "[(1,2),(3,5)]"]]
- DocTest.printPrefix "Data.Interval:243: "
-{-# LINE 243 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:255: "
+{-# LINE 255 "src/Data/Interval.hs" #-}
  DocTest.example
-{-# LINE 243 "src/Data/Interval.hs" #-}
+{-# LINE 255 "src/Data/Interval.hs" #-}
       (without' (1,5) (1,5))
   [ExpectedLine [LineChunk "[]"]]
- DocTest.printPrefix "Data.Interval:245: "
-{-# LINE 245 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:257: "
+{-# LINE 257 "src/Data/Interval.hs" #-}
  DocTest.example
-{-# LINE 245 "src/Data/Interval.hs" #-}
+{-# LINE 257 "src/Data/Interval.hs" #-}
       (without' (1,5) (0,1))
   [ExpectedLine [LineChunk "[(1,5)]"]]
- DocTest.printPrefix "Data.Interval:267: "
-{-# LINE 267 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:279: "
+{-# LINE 279 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 267 "src/Data/Interval.hs" #-}
+{-# LINE 279 "src/Data/Interval.hs" #-}
         (genSortedIntervals /\ all (\xs -> and $ List.zipWith intersects xs (tail xs)) . contiguous)
- DocTest.printPrefix "Data.Interval:282: "
-{-# LINE 282 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:294: "
+{-# LINE 294 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 282 "src/Data/Interval.hs" #-}
+{-# LINE 294 "src/Data/Interval.hs" #-}
         (genSortedIntervals /\ \xs -> all (\i -> any (flip contains i) (components xs)) xs)
- DocTest.printPrefix "Data.Interval:293: "
-{-# LINE 293 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:305: "
+{-# LINE 305 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 293 "src/Data/Interval.hs" #-}
+{-# LINE 305 "src/Data/Interval.hs" #-}
         (genSortedIntervals /\ \xs -> componentsSeq (Seq.fromList xs) == Seq.fromList (components xs))
- DocTest.printPrefix "Data.Interval:306: "
-{-# LINE 306 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:318: "
+{-# LINE 318 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 306 "src/Data/Interval.hs" #-}
+{-# LINE 318 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genIntervalSeq /\ \js -> all (contains i) (covered i js))
- DocTest.printPrefix "Data.Interval:307: "
-{-# LINE 307 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:319: "
+{-# LINE 319 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 307 "src/Data/Interval.hs" #-}
+{-# LINE 319 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genIntervalSeq /\ \js -> covered i (covered i js) == covered i js)
- DocTest.printPrefix "Data.Interval:315: "
-{-# LINE 315 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:327: "
+{-# LINE 327 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 315 "src/Data/Interval.hs" #-}
+{-# LINE 327 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> j `contains` i == i `coveredBy` [j])
- DocTest.printPrefix "Data.Interval:316: "
-{-# LINE 316 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:328: "
+{-# LINE 328 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 316 "src/Data/Interval.hs" #-}
+{-# LINE 328 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genSortedIntervals /\ \js -> i `coveredBy` js ==> any (flip contains i) (components js))
- DocTest.printPrefix "Data.Interval:322: "
-{-# LINE 322 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:334: "
+{-# LINE 334 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 322 "src/Data/Interval.hs" #-}
+{-# LINE 334 "src/Data/Interval.hs" #-}
         (genNonEmptyInterval /\ \i -> genIntervalSeq /\ \js -> i `coveredBy` js == (fractionCovered i js >= (1::Rational)))
- DocTest.printPrefix "Data.Interval:323: "
-{-# LINE 323 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:335: "
+{-# LINE 335 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 323 "src/Data/Interval.hs" #-}
+{-# LINE 335 "src/Data/Interval.hs" #-}
         (genNonEmptyInterval /\ \i -> genNonEmptyIntervalSeq /\ \js -> any (properlyIntersects i) js == (fractionCovered i js > (0::Rational)))
- DocTest.printPrefix "Data.Interval:342: "
-{-# LINE 342 "src/Data/Interval.hs" #-}
- DocTest.property
-{-# LINE 342 "src/Data/Interval.hs" #-}
-        (genInterval /\* \i j -> i `intersects` j  ==  (overlap i j == EQ))
  DocTest.printPrefix "Data.Interval:354: "
 {-# LINE 354 "src/Data/Interval.hs" #-}
  DocTest.property
 {-# LINE 354 "src/Data/Interval.hs" #-}
+        (genInterval /\* \i j -> i `intersects` j  ==  (overlap i j == EQ))
+ DocTest.printPrefix "Data.Interval:372: "
+{-# LINE 372 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 372 "src/Data/Interval.hs" #-}
+        (genInterval /\* \i j -> i `properlyIntersects` j  ==  (properOverlap i j == EQ))
+ DocTest.printPrefix "Data.Interval:384: "
+{-# LINE 384 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 384 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> (lb i <= ub i && lb j <= ub j && i `intersects` j)  ==  (max (lb i) (lb j) <= min (ub i) (ub j)))
- DocTest.printPrefix "Data.Interval:351: "
-{-# LINE 351 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:381: "
+{-# LINE 381 "src/Data/Interval.hs" #-}
  DocTest.example
-{-# LINE 351 "src/Data/Interval.hs" #-}
+{-# LINE 381 "src/Data/Interval.hs" #-}
       (((1,2)::(Int,Int)) `intersects` ((2,3)::(Int,Int)))
   [ExpectedLine [LineChunk "True"]]
- DocTest.printPrefix "Data.Interval:365: "
-{-# LINE 365 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:395: "
+{-# LINE 395 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 365 "src/Data/Interval.hs" #-}
+{-# LINE 395 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> ((i `intersects` j) && not (i `properlyIntersects` j))  ==  (ub i == lb j || ub j == lb i))
- DocTest.printPrefix "Data.Interval:371: "
-{-# LINE 371 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:401: "
+{-# LINE 401 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 371 "src/Data/Interval.hs" #-}
+{-# LINE 401 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> i `contains` i)
- DocTest.printPrefix "Data.Interval:372: "
-{-# LINE 372 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:402: "
+{-# LINE 402 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 372 "src/Data/Interval.hs" #-}
+{-# LINE 402 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> (i `contains` j && j `contains` i) == (i==j))
- DocTest.printPrefix "Data.Interval:373: "
-{-# LINE 373 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:403: "
+{-# LINE 403 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 373 "src/Data/Interval.hs" #-}
+{-# LINE 403 "src/Data/Interval.hs" #-}
         (genInterval /\* \i j -> i `contains` j == (maybeUnion i j == Just i))
- DocTest.printPrefix "Data.Interval:385: "
-{-# LINE 385 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:415: "
+{-# LINE 415 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 385 "src/Data/Interval.hs" #-}
+{-# LINE 415 "src/Data/Interval.hs" #-}
         (genSortedList /\ \xs -> (components $ toList $ fromEndPoints xs) == if length xs < 2 then [] else [(head xs, last xs)])
- DocTest.printPrefix "Data.Interval:398: "
-{-# LINE 398 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:428: "
+{-# LINE 428 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 398 "src/Data/Interval.hs" #-}
+{-# LINE 428 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genSortedIntervalSeq /\ \js -> toList (getIntersects i js) `List.isSubsequenceOf` toList js)
- DocTest.printPrefix "Data.Interval:415: "
-{-# LINE 415 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:445: "
+{-# LINE 445 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 415 "src/Data/Interval.hs" #-}
+{-# LINE 445 "src/Data/Interval.hs" #-}
         (genSortedIntervalSeq /\ \xs -> hullSeq xs == hull (toList xs))
- DocTest.printPrefix "Data.Interval:447: "
-{-# LINE 447 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:464: "
+{-# LINE 464 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 447 "src/Data/Interval.hs" #-}
+{-# LINE 464 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i -> genSortedIntervals /\ \js -> fst (splitIntersecting i js) == filter (intersects i) js)
+ DocTest.printPrefix "Data.Interval:465: "
+{-# LINE 465 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 465 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i -> genSortedIntervals /\ \js -> all (\j -> not (ub j < ub i)) (snd (splitIntersecting i js)))
+ DocTest.printPrefix "Data.Interval:461: "
+{-# LINE 461 "src/Data/Interval.hs" #-}
+ DocTest.example
+{-# LINE 461 "src/Data/Interval.hs" #-}
+      (splitIntersecting ((2,5) :: (Int,Int)) ([(0,1),(2,3),(2,2),(3,6),(6,7)] :: [(Int,Int)]))
+  [ExpectedLine [LineChunk "([(2,3),(2,2),(3,6)],[(3,6),(6,7)])"]]
+ DocTest.printPrefix "Data.Interval:485: "
+{-# LINE 485 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 485 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i -> genSortedIntervals /\ \js -> fst (splitProperlyIntersecting i js) == filter (properlyIntersects i) js)
+ DocTest.printPrefix "Data.Interval:486: "
+{-# LINE 486 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 486 "src/Data/Interval.hs" #-}
+        (genInterval /\ \i -> genSortedIntervals /\ \js -> all (not.contains i) (snd (splitProperlyIntersecting i js)))
+ DocTest.printPrefix "Data.Interval:482: "
+{-# LINE 482 "src/Data/Interval.hs" #-}
+ DocTest.example
+{-# LINE 482 "src/Data/Interval.hs" #-}
+      (splitProperlyIntersecting ((2,5) :: (Int,Int))  ([(0,1),(2,3),(2,2),(3,5),(5,6),(6,7)] :: [(Int,Int)]))
+  [ExpectedLine [LineChunk "([(2,3),(3,5)],[(5,6),(6,7)])"]]
+ DocTest.printPrefix "Data.Interval:523: "
+{-# LINE 523 "src/Data/Interval.hs" #-}
+ DocTest.property
+{-# LINE 523 "src/Data/Interval.hs" #-}
         (invariant . itree 4 . fmap (\(x,y) -> (x, x + QC.getNonNegative y :: Integer)))
- DocTest.printPrefix "Data.Interval:457: "
-{-# LINE 457 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:533: "
+{-# LINE 533 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 457 "src/Data/Interval.hs" #-}
+{-# LINE 533 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genIntervalSeq /\ \t -> on (==) sortByLeft (getIntersectsIT i $ itree 2 t) (i `intersecting` t))
- DocTest.printPrefix "Data.Interval:468: "
-{-# LINE 468 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:544: "
+{-# LINE 544 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 468 "src/Data/Interval.hs" #-}
+{-# LINE 544 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genIntervalSeq /\ \t -> on (==) sortByLeft (getProperIntersectsIT i $ itree 2 t) (i `intersectingProperly` t))
- DocTest.printPrefix "Data.Interval:573: "
-{-# LINE 573 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:649: "
+{-# LINE 649 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 573 "src/Data/Interval.hs" #-}
+{-# LINE 649 "src/Data/Interval.hs" #-}
         (genIntervalSeq /\ \is -> joinSeq (splitSeq is) == is)
- DocTest.printPrefix "Data.Interval:630: "
-{-# LINE 630 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:706: "
+{-# LINE 706 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 630 "src/Data/Interval.hs" #-}
+{-# LINE 706 "src/Data/Interval.hs" #-}
         (genDisjointIntervalSeq /\ \xs -> hullSeqNonOverlap xs == hullSeq xs)
- DocTest.printPrefix "Data.Interval:647: "
-{-# LINE 647 "src/Data/Interval.hs" #-}
+ DocTest.printPrefix "Data.Interval:732: "
+{-# LINE 732 "src/Data/Interval.hs" #-}
  DocTest.property
-{-# LINE 647 "src/Data/Interval.hs" #-}
+{-# LINE 732 "src/Data/Interval.hs" #-}
         (genInterval /\ \i -> genDisjointIntervalSeq /\ \js -> findSeq intersects i js == intersecting i js)
diff --git a/src/Data/Interval.hs b/src/Data/Interval.hs
--- a/src/Data/Interval.hs
+++ b/src/Data/Interval.hs
@@ -50,6 +50,7 @@
     intersects,properlyIntersects,contains,properlyContains,
     covered,coveredBy,overlapTime,prevailing,fractionCovered,
     overlap,
+    properOverlap,
     intervalDuration,
     -- * Operations on intervals
     maybeUnion,maybeIntersection,
@@ -59,6 +60,9 @@
     contiguous,components,componentsSeq,
     sortByLeft,
     fromEndPoints,
+    -- * Streaming intervals
+    splitIntersecting,
+    splitProperlyIntersecting,
     -- * Interval search tree
     ITree,
     itree,
@@ -140,16 +144,20 @@
     -- ^ does any interval touch the first one?
     someProperlyIntersects :: (Interval e i, Interval e j) => i -> t j -> Bool
     -- ^ does any interval properly intersect the first one?
+    maybeBounds :: Interval e i => t i -> Maybe (e,e)
+    -- ^ the convex hull of the contents
 instance Ord e => IntersectionQuery (ITree e) e Seq where
     getIntersects = getIntersectsIT
     getProperIntersects = getProperIntersectsIT
     someIntersects = someIntersectsIT
     someProperlyIntersects = someProperlyIntersectsIT
+    maybeBounds = hullOfTree 
 instance Ord e => IntersectionQuery Seq e Seq where
     getIntersects = findSeq intersects
     getProperIntersects = findSeq properlyIntersects
     someIntersects = existsSeq intersects
     someProperlyIntersects = existsSeq properlyIntersects
+    maybeBounds = hullSeqNonOverlap 
 
 -- | Time types supporting differences
 class TimeDifference t where
@@ -344,12 +352,30 @@
 -- i.e., 'overlap' is not transitive.
 --
 -- prop> genInterval /\* \i j -> i `intersects` j  ==  (overlap i j == EQ)
-overlap :: Interval e i => i -> i -> Ordering
+overlap :: (Interval e i, Interval e j) => i -> j -> Ordering
 overlap i j = case (compare (ub i) (lb j),compare (ub j) (lb i)) of
     (LT,_) -> LT
     (_,LT) -> GT
     _      -> EQ
 
+-- | Overlap ordering. Returns 'LT' or 'GT' if the intervals 
+-- are disjoint or touch in end point(s) only,
+-- 'EQ' if the intervals properly overlap.
+-- Note that this violates the following property:
+--
+-- @
+-- 'properOverlap' x y == 'EQ' && 'properOverlap' y z == 'EQ' => 'properOverlap' x z == 'EQ'
+-- @
+--
+-- i.e., 'properOverlap' is not transitive.
+--
+-- prop> genInterval /\* \i j -> i `properlyIntersects` j  ==  (properOverlap i j == EQ)
+properOverlap :: (Interval e i, Interval e j) => i -> j -> Ordering
+properOverlap i j = case ((ub i) <= (lb j),(ub j) <= (lb i)) of
+    (True,_) -> LT
+    (_,True) -> GT
+    _      -> EQ
+
 -- | intersection query.
 --
 -- >>> ((1,2)::(Int,Int)) `intersects` ((2,3)::(Int,Int))
@@ -422,6 +448,52 @@
     EmptyL -> Nothing
     leftmost :< _others -> Just (lb leftmost, maximum (fmap ub xs))
 
+-- | When you face the problem of matching two series of intervals against each other, 
+-- a streaming approach might be more efficient than transforming 
+-- one of the streams into a search structure. 
+-- This function drops intervals from the list until 
+-- the (contiguous, see 'sortByLeft') block of intersecting intervals 
+-- is found. This block (except intervals containing the 'ub' of the query) 
+-- is removed from the stream. 
+-- When used as a state transformer on a stream @[i]@ of non-properly overlapping intervals, 
+-- then one obtains the stream of blocks intersecting the stream of queries. 
+-- 
+-- >>> splitIntersecting ((2,5) :: (Int,Int)) ([(0,1),(2,3),(2,2),(3,6),(6,7)] :: [(Int,Int)])
+-- ([(2,3),(2,2),(3,6)],[(3,6),(6,7)])
+--
+-- prop> genInterval /\ \i -> genSortedIntervals /\ \js -> fst (splitIntersecting i js) == filter (intersects i) js
+-- prop> genInterval /\ \i -> genSortedIntervals /\ \js -> all (\j -> not (ub j < ub i)) (snd (splitIntersecting i js))
+splitIntersecting :: (Interval e i, Interval e j) => i -> [j] -> ([j],[j])
+splitIntersecting _ [] = ([],[])
+splitIntersecting i js@(j:js') = case i `overlap` j of
+    GT -> splitIntersecting i js'
+    LT -> ([],js)
+    EQ -> let 
+        keep = ub j >= ub i
+        (block,notIntersecting) = splitIntersecting i js'
+        in (j:block,if keep then j:notIntersecting else notIntersecting)
+
+-- | Like 'splitIntersecting' but disregards those intervals 
+-- that merely touch the query. 
+-- Retains overlapping intervals properly containing the 'ub' of the query. 
+-- When used as a state transformer on an ascending stream @[i]@ of non-properly overlapping intervals, 
+-- then one obtains the stream of blocks properly intersecting the stream of queries.
+-- 
+-- >>> splitProperlyIntersecting ((2,5) :: (Int,Int))  ([(0,1),(2,3),(2,2),(3,5),(5,6),(6,7)] :: [(Int,Int)])
+-- ([(2,3),(3,5)],[(5,6),(6,7)])
+--
+-- prop> genInterval /\ \i -> genSortedIntervals /\ \js -> fst (splitProperlyIntersecting i js) == filter (properlyIntersects i) js
+-- prop> genInterval /\ \i -> genSortedIntervals /\ \js -> all (not.contains i) (snd (splitProperlyIntersecting i js))
+splitProperlyIntersecting :: (Interval e i, Interval e j) => i -> [j] -> ([j],[j])
+splitProperlyIntersecting _ [] = ([],[])
+splitProperlyIntersecting i js@(j:js') = case i `properOverlap` j of
+    GT -> splitProperlyIntersecting i js'
+    LT -> ([],js)
+    EQ -> let 
+        keep = ub j > ub i
+        (block,notIntersecting) = splitProperlyIntersecting i js'
+        in (j:block,if keep then j:notIntersecting else notIntersecting)
+
 -- | Search tree of intervals.
 data ITree e i = Bin (Seq i) | Split (Seq i) e e e (ITree e i) (ITree e i)
 -- Internal nodes store the convex hull of its subtrees.
@@ -638,10 +710,6 @@
     leftmost :< others -> Just (lb leftmost, case Seq.viewr others of
         _ :> rightmost -> maybe (ub rightmost) ub (findLeftmost ((lb rightmost ==).lb) xs)
         EmptyR         -> ub leftmost)
--- TODO: This fails e.g. for 
--- [(0,2),(0,0)] 
--- for the upper bound need to perform binary search 
--- for the left-most interval i with lb i == lb rightmost
 
 findLeftmost :: (i -> Bool) -> Seq i -> Maybe i
 findLeftmost p = go where 
