module BatOrd:sig..end
Traditional OCaml code, under the influence of C comparison
functions, has used int-returning comparisons (< 0, 0 or >
0). Using an algebraic datatype instead is actually nicer, both
for comparison producers (no arbitrary choice of a positive and
negative value) and consumers (nice pattern-matching elimination).
type order =
| |
Lt |
|||
| |
Eq |
|||
| |
Gt |
(* | An algebraic datatype for ordering.
Traditional OCaml code, under the influence of C comparison functions, has used int-returning comparisons (< 0, 0 or > 0). Using an algebraic datatype instead is actually nicer, both for comparison producers (no arbitrary choice of a positive and negative value) and consumers (nice pattern-matching elimination). | *) |
type'aord ='a -> 'a -> order
order variant.type'acomp ='a -> 'a -> int
module type Comp =sig..end
compare as member name instead of comp, so that the
Comp modules can be used as the legacy OrderedType interface.
module type Ord =sig..end
val ord0 : int -> orderval ord : 'a comp -> 'a ordmodule Ord:
val comp0 : order -> intval comp : 'a ord -> 'a compmodule Comp:
val poly_comp : 'a compval poly_ord : 'a ordval poly : 'a ordPervasives.compare function from inria's stdlib, have
polymorphic types: they claim to be able to compare values of any
type. In practice, they work for only some types, may fail on
function types and may not terminate on cyclic values.
They work by runtime magic, inspecting the values in an untyped
way. While being an useful hack for base types and simple
composite types (say (int * float) list, they do not play well
with functions, type abstractions, and structures that would need
a finer notion of equality/comparison. For example, if one
represent sets as balanced binary tree, one may want set with
equal elements but different balancings to be equal, which would
not be the case using the polymorphic equality function.
When possible, you should therefore avoid relying on these
polymorphic comparison functions. You should be especially careful
if your data structure may later evolve to allow cyclic data
structures or functions.
val rev_ord0 : order -> orderval rev_comp0 : int -> intval rev_ord : 'a ord -> 'a ordval rev_comp : 'a comp -> 'a compval rev : 'a ord -> 'a ordInt.ord sorts integer by increasing
order, rev Int.ord will sort them by decreasing order.module RevOrd:
module RevComp:
module Rev:
type'aeq ='a -> 'a -> bool
All ordered types also support equality, as equality can be
derived from ordering. However, there are also cases where
elements may be compared for equality, but have no natural
ordering. It is therefore useful to provide equality as an
independent notion.
val eq_ord0 : order -> boolval eq_comp0 : int -> boolval eq_ord : 'a ord -> 'a eqval eq_comp : 'a comp -> 'a eqval eq : 'a ord -> 'a eqmodule type Eq =sig..end
module EqOrd:
module EqComp:
module Eq:
type'achoice ='a -> 'a -> 'a
min and max.val min_ord : 'a ord -> 'a choiceval max_ord : 'a ord -> 'a choiceval min_comp : 'a comp -> 'a choiceval max_comp : 'a comp -> 'a choiceval min : 'a ord -> 'a choicemin ord will choose the smallest element, according to ord.
For example, min Int.ord 1 2 will return 1.
(* the minimum element of a list *)
let list_min ord = List.reduce (min ord)
val max : 'a ord -> 'a choicemax ord will choose the biggest element according to ord.val bin_comp : 'a comp -> 'a -> 'a -> 'b comp -> 'b -> 'b -> intval bin_ord : 'a ord -> 'a -> 'a -> 'b ord -> 'b -> 'b -> orderbin_ord ord1 v1 v1' ord2 v2 v2' is ord2 v2 v2' if ord1 v1 v1' = Eq,
and ord1 v1 v1' otherwhise.val bin_eq : 'a eq -> 'a -> 'a -> 'b eq -> 'b -> 'b -> boolval map_eq : ('a -> 'b) -> 'b eq -> 'a eqval map_comp : ('a -> 'b) -> 'b comp -> 'a compval map_ord : ('a -> 'b) -> 'b ord -> 'a ordmap_ord Set.cardinal Int.ord.
The input of the mapping function is the type you want to compare,
so this is the reverse of List.map.module Incubator:sig..end