It offers most of the functions in Data.Map, but Intervalk instead of
just k as the key type. Some of the functions need stricter type constraints to
maintain the additional information for efficient interval searching,
for example fromDistinctAscList needs an Ordk constraint.

Index-based access and some set functions have not been implemented, and many non-core
functions, for example the set operations, have not been tuned for efficiency yet.

In addition, there are functions specific to maps of intervals, for example to search
for all keys containing a given point or contained in a given interval.

To stay compatible with standard Haskell, this implementation uses a fixed data
type for intervals, and not a multi-parameter type class. Thus, it's currently
not possible to define e.g. a 2-tuple as an instance of interval and use that
map key. Instead you must convert your keys to Data.IntervalMap.Interval.

Closed, open, and half-open intervals can be contained in the same map.

It is an error to insert an empty interval into a map. This precondition is not
checked by the various insertion functions.

The implementation is a red-black tree augmented with the maximum upper bound
of all keys.

Parts of this implementation are based on code from the Data.Map implementation,
(c) Daan Leijen 2002, (c) Andriy Palamarchuk 2008.
The red-black tree deletion is based on code from llrbtree by Kazu Yamamoto.
Of course, any errors are mine.

re-export

Read and Show use mathematical notation with square brackets for closed
and parens for open intervals.
This is better for human readability, but is not a valid Haskell expression.
Closed intervals look like a list, open intervals look like a tuple,
and half-open intervals look like mismatched parens.

O(log n). Insert with a function, combining new value and old value.
insertWith f key value mp
will insert the pair (key, value) into mp if key does
not exist in the map. If the key does exist, the function will
insert the pair (key, f new_value old_value).

O(log n). Insert with a function, combining key, new value and old value.
insertWithKey f key value mp
will insert the pair (key, value) into mp if key does
not exist in the map. If the key does exist, the function will
insert the pair (key, f key new_value old_value).
Note that the key passed to f is the same key passed to insertWithKey.

O(log n). The expression (updateWithKey f k map) updates the
value x at k (if it is in the map). If (f k x) is Nothing,
the element is deleted. If it is (Just y), the key k is bound
to the new value y.

O(n+m). Difference with a combining function.
When two equal keys are
encountered, the combining function is applied to the values of these keys.
If it returns Nothing, the element is discarded (proper set difference). If
it returns (Just y), the element is updated with a new value y.

O(n+m). Difference with a combining function. When two equal keys are
encountered, the combining function is applied to the key and both values.
If it returns Nothing, the element is discarded (proper set difference). If
it returns (Just y), the element is updated with a new value y.

O(n+m). Is this a proper submap? (ie. a submap but not equal).
The expression (isProperSubmapOfBy f m1 m2) returns True when
m1 and m2 are not equal,
all keys in m1 are in m2, and when f returns True when
applied to their respective values.