Summary: A comparer `('a, 'compare_a) t` for type `'a` is a "compare" function of type `'a -> 'a -> int` tagged with a phantom type `'compare_a` acting as a singleton type denoting an individual compare function. The point of these is to enable writing type definitions of containers that depend on a compare function prior to applying a functor. For example, a type of sorted lists could be exposed as: ``` type elt type (elt, 'compare_elt) t = private elt list ``` and the operations manipulating sorted lists would be defined by a functor that accepts a `Comparer.S` and implements the operations using ``` let compare = (comparer :> elt -> elt -> int) ``` Reviewed By: ngorogiannis Differential Revision: D26250528 fbshipit-source-id: ea61844ecmaster
parent
5d54631d09
commit
7cf6e17403
@ -0,0 +1,86 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
(** Singleton types for compare functions *)
|
||||
|
||||
type ('a, 'compare_a) t = 'a -> 'a -> int
|
||||
|
||||
module type S = sig
|
||||
type ('a, 'compare_a) comparer := ('a, 'compare_a) t
|
||||
type t
|
||||
type compare [@@deriving compare, equal, sexp]
|
||||
|
||||
val comparer : (t, compare) comparer
|
||||
end
|
||||
|
||||
module type S1 = sig
|
||||
type ('a, 'compare_a) comparer := ('a, 'compare_a) t
|
||||
type 'a t
|
||||
type 'compare_a compare [@@deriving compare, equal, sexp]
|
||||
|
||||
val comparer :
|
||||
('a, 'compare_a) comparer -> ('a t, 'compare_a compare) comparer
|
||||
end
|
||||
|
||||
module Make (Ord : sig
|
||||
type t [@@deriving compare]
|
||||
end) =
|
||||
struct
|
||||
include Ord
|
||||
|
||||
type compare [@@deriving compare, equal, sexp]
|
||||
|
||||
let comparer = Ord.compare
|
||||
end
|
||||
|
||||
module Counterfeit (Ord : sig
|
||||
type t [@@deriving compare]
|
||||
type compare [@@deriving compare, equal, sexp]
|
||||
end) =
|
||||
struct
|
||||
include Ord
|
||||
|
||||
let comparer = Ord.compare
|
||||
end
|
||||
|
||||
module Apply (F : sig
|
||||
type ('a, 'compare_a) t [@@deriving compare]
|
||||
type 'compare_a compare [@@deriving compare, equal, sexp]
|
||||
end)
|
||||
(A : S) =
|
||||
struct
|
||||
module A = struct
|
||||
include A
|
||||
|
||||
let compare = comparer
|
||||
end
|
||||
|
||||
type t = (A.t, A.compare) F.t [@@deriving compare]
|
||||
type compare = A.compare F.compare [@@deriving compare, equal, sexp]
|
||||
|
||||
let comparer = compare
|
||||
end
|
||||
|
||||
module Apply1 (F : sig
|
||||
type ('a, 'b, 'compare_a) t [@@deriving compare]
|
||||
type ('compare_a, 'compare_b) compare [@@deriving compare, equal, sexp]
|
||||
end)
|
||||
(A : S) =
|
||||
struct
|
||||
module A = struct
|
||||
include A
|
||||
|
||||
let compare = comparer
|
||||
end
|
||||
|
||||
type 'b t = (A.t, 'b, A.compare) F.t [@@deriving compare]
|
||||
|
||||
type 'b compare = (A.compare, 'b) F.compare
|
||||
[@@deriving compare, equal, sexp]
|
||||
|
||||
let comparer = compare
|
||||
end
|
@ -0,0 +1,86 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
(** Singleton types for compare functions *)
|
||||
|
||||
(** A comparer [('a, 'compare_a) t] for type ['a] is a "compare" function of
|
||||
type ['a -> 'a -> int] tagged with a phantom type ['compare_a] acting as
|
||||
a singleton type denoting an individual compare function. *)
|
||||
type ('a, 'compare_a) t = private 'a -> 'a -> int
|
||||
|
||||
module type S = sig
|
||||
type ('a, 'compare_a) comparer := ('a, 'compare_a) t
|
||||
type t
|
||||
|
||||
(** [compare] types are equipped with functions to support use of
|
||||
[@@deriving compare, equal, sexp] on types parameterized by such
|
||||
singleton types for compare functions. These derived functions are
|
||||
never actually called, since the compare type parameters are phantom. *)
|
||||
type compare [@@deriving compare, equal, sexp]
|
||||
|
||||
val comparer : (t, compare) comparer
|
||||
end
|
||||
|
||||
(** [Make] takes a [compare] function, mints a fresh [compare] type to act
|
||||
as a singleton type denoting that one compare function, and returns the
|
||||
[compare] function at a type stamped with its singleton type. In this
|
||||
way, [Make] applied to two different compare functions for the same type
|
||||
of values yields comparers with incompatible types. *)
|
||||
module Make (Ord : sig
|
||||
type t [@@deriving compare]
|
||||
end) : S with type t = Ord.t
|
||||
|
||||
(** [Counterfeit] takes a compare function and type and yields a comparer
|
||||
that asserts that the given [compare] type is a singleton for the given
|
||||
[compare] function. This is not checked by the type system. It is the
|
||||
client's responsibility to ensure that distinct types are provided for
|
||||
distinct compare functions. If the same type is used for multiple
|
||||
functions, then [Counterfeit] will produce type-compatible comparers
|
||||
even though the wrapped compare functions differ. *)
|
||||
module Counterfeit (Ord : sig
|
||||
type t [@@deriving compare]
|
||||
type compare [@@deriving compare, equal, sexp]
|
||||
end) : S with type t = Ord.t with type compare = Ord.compare
|
||||
|
||||
(** [Apply (F) (A)] takes a type [('a, 'compare_a) F.t] with a type
|
||||
parameter ['a] and a compare type ['compare_a] for ['a], and a comparer
|
||||
[A], and creates a comparer for [F.t] with ['a] instantiated to [A.t]. *)
|
||||
module Apply (F : sig
|
||||
type ('a, 'compare_a) t [@@deriving compare]
|
||||
type 'compare_a compare [@@deriving compare, equal, sexp]
|
||||
end)
|
||||
(A : S) : sig
|
||||
type t = (A.t, A.compare) F.t [@@deriving compare]
|
||||
|
||||
include S with type t := t with type compare = A.compare F.compare
|
||||
end
|
||||
|
||||
module type S1 = sig
|
||||
type ('a, 'compare_a) comparer := ('a, 'compare_a) t
|
||||
type 'a t
|
||||
type 'compare_a compare [@@deriving compare, equal, sexp]
|
||||
|
||||
val comparer :
|
||||
('a, 'compare_a) comparer -> ('a t, 'compare_a compare) comparer
|
||||
end
|
||||
|
||||
(** [Apply1 (F) (A)] takes a type [('a, 'b, 'compare_a) F.t] with two type
|
||||
parameters ['a], ['b] and a compare type ['compare_a] for ['a], and a
|
||||
comparer [A], and creates a comparer for [F.t] with ['a] instantiated to
|
||||
[A.t]. *)
|
||||
module Apply1 (F : sig
|
||||
type ('a, 'b, 'compare_a) t [@@deriving compare]
|
||||
type ('compare_a, 'compare_b) compare [@@deriving compare, equal, sexp]
|
||||
end)
|
||||
(A : S) : sig
|
||||
type 'b t = (A.t, 'b, A.compare) F.t [@@deriving compare]
|
||||
|
||||
include
|
||||
S1
|
||||
with type 'b t := 'b t
|
||||
with type 'compare_b compare = (A.compare, 'compare_b) F.compare
|
||||
end
|
Loading…
Reference in new issue