You could use a functor which requires a module implementing a signature that contains those 3 functions and a type. Similar to what is done with Set or Map.
module type My_Dim =
sig
type t [@@deriving sexp]
val (+): t -> t -> t
val (-): t -> t -> t
val min: t -> t -> t
val max: t -> t -> t
end
module Rect (D: My_Dim) = struct
type t = {
x0: D.t;
y0: D.t;
x1: D.t;
y1: D.t;
} [@@deriving sexp];;
let min_x (r: t) = D.min r.x0 r.x1;;
let min_y (r: t) = D.min r.y0 r.y1;;
let width (r: t) = D.((max r.x0 r.x1) - (min r.x0 r.x1));;
let height (r: t) = D.((max r.y0 r.y1) - (min r.y0 r.y1));;
(*
let map (fx: 'a -> 'b) (fy: 'a -> 'b) (r: 'a t ) : 'b t =
{ x0 = fx r.x0;
x1 = fx r.x1;
y0 = fy r.y0;
y1 = fy r.y1; }
*)
end
I need some help with the commented out function. The idea I want to express is:
given D: My_Dim, D2: My_Dim, fx: D.t → D2.t, fy: D.t → D2.t, r: D Rect.t
we can produce a D2 Rect.t
module type My_Dim =
sig
type t [@@deriving sexp]
val (+): t -> t -> t
val (-): t -> t -> t
val min: t -> t -> t
val max: t -> t -> t
end
module Rect (D: My_Dim) = struct
type t = {
x0: D.t;
y0: D.t;
x1: D.t;
y1: D.t;
} [@@deriving sexp];;
let min_x (r: t) = D.min r.x0 r.x1;;
let min_y (r: t) = D.min r.y0 r.y1;;
let width (r: t) = D.((max r.x0 r.x1) - (min r.x0 r.x1));;
let height (r: t) = D.((max r.y0 r.y1) - (min r.y0 r.y1));;
end
module RectConv (D1: My_Dim) (D2: My_Dim) = struct
let map (fx: D1.t -> D2.t) (fy: D1.t -> D2.t) (r: Rect(D1).t ) : Rect(D2).t =
{ x0 = fx r.x0;
x1 = fx r.x1;
y0 = fy r.y0;
y1 = fy r.y1; }
end
if you move a type out of the Rect functor then you can get rid of RectConv?
type 'a rect = {
x0 : 'a;
y0 : 'a;
x1 : 'a;
y1 : 'a;
}
module type My_Dim = sig
type t
val ( + ) : t -> t -> t
val ( - ) : t -> t -> t
val min : t -> t -> t
val max : t -> t -> t
end
module Rect (D : My_Dim) = struct
type t = D.t rect
let min_x (r : t) = D.min r.x0 r.x1
let min_y (r : t) = D.min r.y0 r.y1
let width (r : t) = D.(max r.x0 r.x1 - min r.x0 r.x1)
let height (r : t) = D.(max r.y0 r.y1 - min r.y0 r.y1)
end
let map fx fy r = { x0 = fx r.x0; x1 = fx r.x1; y0 = fy r.y0; y1 = fy r.y1 }