I have written the following two files, and although it works, it feels odd that the code would duplicate these long type declarations. On the other hand, if I remove either module type declaration then the code no longer compiles.
Is there a more proper way to write this kind of thing? Or is it correct to duplicate these type declarations in the .mli and .ml files?
set.mli
module type Element = sig
type t
val create : 'a -> t
val compare : t -> t -> int
val to_string : t -> string
end
module type Set = sig
type t
val empty : unit -> t
end
module Make : functor (M : Element) -> Set with type t = M.t list
set.ml
module type Element = sig
type t
val create : 'a -> t
val compare : t -> t -> int
val to_string : t -> string
end
module type Set = sig
type t
val empty : unit -> t
end
module Make (M:Element) = struct
type t = M.t list
let emtpy () = []
end
A good reference for this would be to review how the standard library is implemented. It's doubtful you're going to find a "better" way to do things than they do.
I you consider set.mli and set.ml you'll see that they are specified very similarly to your code.
What is curious in your code is why empty
is implemented as a function, rather than simply a value. Note that you have a typo with emtpy
in your second to last line.