This module implements bag and set operations on ordered lists.
Except for variations of the sort and isSorted functions,
every function assumes that any list arguments are sorted lists.
Assuming this precondition is met, every resulting list is also
sorted.

Note that these functions handle multisets, and are left-biased.
Thus, even assuming the arguments are sorted, isect does not always
return the same results as Data.List.intersection, due to multiplicity.

The has function returns True if the element appears in the list;
it is equivalent to member except the order of the arguments is reversed,
making it a function from an ordered list to its characteristic function.

Set-like operations

The isect function computes the intersection of two ordered lists.
An element occurs in the output as many times as the minimum number of
occurences in either input. If either input is a set, then the output
is a set.

The union function computes the union of two ordered lists.
An element occurs in the output as many times as the maximum number
of occurences in either input. If both inputs are sets, then the
output is a set.

The minus function computes the difference of two ordered lists.
An element occurs in the output as many times as it occurs in
the first input, minus the number of occurrences in the second input.
If the first input is a set, then the output is a set.

The xunion function computes the exclusive union of two ordered lists.
An element occurs in the output as many times as the absolute difference
between the number of occurrences in the inputs. If both inputs
are sets, then the output is a set.

The mergeAll function generalizes "foldrmerge []" to a
(possibly infinite) list of (possibly infinite) ordered lists. To make
this possible, it adds the assumption that the heads of the non-empty
lists themselves form a sorted list.

The implementation is based on the article "Implicit Heaps" by
Heinrich Apfelmus, which simplifies an algorithm by Dave Bayer.

The unionAll function generalizes "foldrunion []" to a
(possibly infinite) list of (possibly infinite) ordered lists.
To make this possible, it adds the assumption that the heads of the
non-empty lists themselves form a sorted list.

The library implementation is based on some of the same techniques
as used in mergeAll. However, the analogous simple definition
is not entirely satisfactory, because

The nubBy function is the greedy algorithm that returns a
sublist of its input such that:

isSortedBy pred (nubBy pred xs) == True

This is true for all lists, not just ordered lists, and all binary
predicates, not just total orders. On infinite lists, this statement
is true in a certain mathematical sense, but not a computational one.

This variant of sortOn recomputes the sorting key every comparison.
This can be better for functions that are cheap to compute.
This is definitely better for projections, as the decorate-sort-undecorate
saves nothing and adds two traversals of the list and extra memory
allocation.

The nubSort function is equivalent to nub.sort, except
somewhat more efficient as duplicates are removed as it sorts. It is
essentially Data.List.sort, a mergesort by Ian Lynagh, with merge
replaced by union.