jon.recoil.org

Source file comparator_intf.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
(** Comparison and serialization for a type, using a witness type to distinguish between
    comparison functions with different behavior. *)

open! Import
module Sexp = Sexp0

module Definitions (T : sig
    type (_, _) comparator
  end) =
struct
  open T

  [%%template
  [@@@modality.default p = (nonportable, portable)]

  module type S = sig
    type t
    type comparator_witness : value mod p

    val comparator : (t, comparator_witness) comparator
  end

  module type S1 = sig
    type 'a t
    type comparator_witness : value mod p

    val comparator : ('a t, comparator_witness) comparator
  end

  module type S_fc = sig
    type comparable_t

    include S [@modality p] with type t := comparable_t
  end

  module type Derived = sig
    type 'a t
    type !'cmp comparator_witness : value mod p with 'cmp

    val comparator : ('a, 'cmp) comparator -> ('a t, 'cmp comparator_witness) comparator
  end

  module type Derived2 = sig
    type ('a, 'b) t
    type (!'cmp_a, !'cmp_b) comparator_witness : value mod p with 'cmp_a with 'cmp_b

    val comparator
      :  ('a, 'cmp_a) comparator
      -> ('b, 'cmp_b) comparator
      -> (('a, 'b) t, ('cmp_a, 'cmp_b) comparator_witness) comparator
  end

  module type Derived_phantom = sig
    type ('a, 'b) t
    type !'cmp comparator_witness : value mod p with 'cmp

    val comparator
      :  ('a, 'cmp) comparator
      -> (('a, _) t, 'cmp comparator_witness) comparator
  end

  module type Derived2_phantom = sig
    type ('a, 'b, 'c) t
    type (!'cmp_a, !'cmp_b) comparator_witness : value mod p with 'cmp_a with 'cmp_b

    val comparator
      :  ('a, 'cmp_a) comparator
      -> ('b, 'cmp_b) comparator
      -> (('a, 'b, _) t, ('cmp_a, 'cmp_b) comparator_witness) comparator
  end]
end

module type Comparator = sig @@ portable
  (** [('a, 'witness) t] contains a comparison function for values of type ['a]. Two
      values of type [t] with the same ['witness] are guaranteed to have the same
      comparison function.

      In OxCaml, [('a, 'witness) t] additionally tracks whether or not the underlying
      comparison function is portable using the ['witness] parameter - if the ['witness]
      type crosses portability, then the comparison function is known to be portable. *)
  type ('a, 'witness) t : value mod contended portable with 'witness @@ contended

  (*_ See the SAFETY comment in the .ml file *)

  val compare : ('a, 'witness) t -> 'a -> 'a -> int
  val sexp_of_t : ('a, 'witness) t -> 'a -> Sexp.t

  module T : sig
    type ('a, 'b) comparator = ('a, 'b) t
  end

  include module type of struct
    include T
    include Definitions (T)
  end

  (** [make] creates a comparator witness for the given comparison. It is intended as a
      lightweight alternative to the functors below, to be used like so:

      {[
        include (val Comparator.make ~compare ~sexp_of_t)
      ]} *)
  val%template make
    :  compare:('a -> 'a -> int) @ p
    -> sexp_of_t:('a -> Sexp.t) @ p
    -> ((module S_fc with type comparable_t = 'a)[@mode p])
  [@@mode p = (nonportable, portable)]

  module%template Poly : S1 [@modality portable] with type 'a t = 'a

  module Module : sig
    (** First-class module providing a comparator and witness type. *)
    type ('a, 'b) t = (module S with type t = 'a and type comparator_witness = 'b)
  end

  val of_module : ('a, 'b) Module.t -> ('a, 'b) t
  val to_module : ('a, 'b) t -> ('a, 'b) Module.t

  module%template.portable S_to_S1 (S : S) :
    S1 with type 'a t = S.t with type comparator_witness = S.comparator_witness

  [%%template:
  [@@@mode.default m = (local, global)]

  (** [Make] creates a [comparator] value and its phantom [comparator_witness] type for a
      nullary type. *)
  module%template.portable
    [@modality p] Make (M : sig
      type t [@@deriving (compare [@mode m]), sexp_of]
    end) : S [@modality p] with type t := M.t

  (** [Make1] creates a [comparator] value and its phantom [comparator_witness] type for a
      unary type. It takes a [compare] and [sexp_of_t] that have non-standard types
      because the [Comparator.t] type doesn't allow passing in additional values for the
      type argument. *)
  module%template.portable
    [@modality p] Make1 (M : sig
      type 'a t

      val compare : 'a t @ m -> 'a t @ m -> int [@@mode m = (global, m)]
      val sexp_of_t : _ t -> Sexp.t
    end) : S1 [@modality p] with type 'a t := 'a M.t

  (** [Derived] creates a [comparator] function that constructs a comparator for the type
      ['a t] given a comparator for the type ['a]. *)
  module%template.portable
    [@modality p] Derived (M : sig
      type 'a t [@@deriving (compare [@mode m]), sexp_of]
    end) : Derived [@modality p] with type 'a t := 'a M.t

  (** [Derived2] creates a [comparator] function that constructs a comparator for the type
      [('a, 'b) t] given comparators for the type ['a] and ['b]. *)
  module%template.portable
    [@modality p] Derived2 (M : sig
      type ('a, 'b) t [@@deriving (compare [@mode m]), sexp_of]
    end) : Derived2 [@modality p] with type ('a, 'b) t := ('a, 'b) M.t

  (** [Derived_phantom] creates a [comparator] function that constructs a comparator for
      the type [('a, 'b) t] given a comparator for the type ['a]. *)
  module%template.portable
    [@modality p] Derived_phantom (M : sig
      type ('a, 'b) t

      val compare : ('a @ m -> 'a @ m -> int) -> ('a, 'b) t @ m -> ('a, 'b) t @ m -> int
      [@@mode m = (global, m)]

      val sexp_of_t : ('a -> Sexp.t) -> ('a, _) t -> Sexp.t
    end) : Derived_phantom [@modality p] with type ('a, 'b) t := ('a, 'b) M.t

  (** [Derived2_phantom] creates a [comparator] function that constructs a comparator for
      the type [('a, 'b, 'c) t] given a comparator for the types ['a] and ['b]. *)
  module%template.portable
    [@modality p] Derived2_phantom (M : sig
      type ('a, 'b, 'c) t

      val compare
        :  ('a @ m -> 'a @ m -> int)
        -> ('b @ m -> 'b @ m -> int)
        -> ('a, 'b, 'c) t @ m
        -> ('a, 'b, 'c) t @ m
        -> int
      [@@mode m = (global, m)]

      val sexp_of_t : ('a -> Sexp.t) -> ('b -> Sexp.t) -> ('a, 'b, _) t -> Sexp.t
    end) : Derived2_phantom [@modality p] with type ('a, 'b, 'c) t := ('a, 'b, 'c) M.t]
end