I’m trying to create a container for values with some shared behaviours. This is the setup boiled down to an absolute minimum.
module type Thing = sig
type t
val compare : t -> t -> int
end
module Int_thing : (Thing with type t = int) = struct
type t = int
let compare = Int.compare
end
module Bool_thing : (Thing with type t = bool) = struct
type t = bool
let compare = Bool.compare
end
module Range (M: Thing) = struct
type t = {lower: M.t; upper: M.t}
let is_valid (rng:t) : bool = M.compare rng.lower rng.upper <= 0
end
module Int_range = Range(Int_thing)
let r0 : Int_range.t = { lower=10; upper=20 }
let r0_is_valid = Int_range.is_valid r0
So that all works fine in a single file with utop - I can create ranges of different things and the “with” lets me easily construct “Things” where they are a simple wrapper around a built-in type.
But - I’m failing at what feels like the simple task of splitting that up into separate files. My googling failed me and I can’t see any examples in the source of a couple of libraries I downloaded.
The problem I think boils down to two questions.
Firstly - Thing
. I think I have to embed the “module type” inside a separate module - it can’t be it’s own file. So: something.mli
and then reference it as Something.Thing
. Is that correct?
Secondly - how do I then reference Thing
in bool_thing.mli
and similar? I couldn’t find the right incantation and ended up just copying+pasting the signature for each concrete module.
TIA