I have the following module type:
module type Element = sig
type t
type mystruct = {x: int; y: int}
val (<) : t -> t -> bool
val string_of_element : t -> string
(* val (>) : t -> t -> bool = not (<) *)
end
Where as you can see, I want the type t
to be generic but I want mystruct
to have a specific structure. The problem is that when I create a module MyInteger
that "implements" module Element
as follow:
module MyInteger = struct
type t = int
let (<) a b = a < b
let string_of_element = string_of_int
end
It complains that
The type `mystruct' is required but not provided
And it does not work unless I redefine type mystruct
in this module.
I don't understand why it just don't use the type I defined in the module type? Is there a way I can make it do that?
Same thing with function (>)
, how can I make OCaml consider (>)
the opposite of (<)
whatever it is?
You were on the right track by tagging "functor." When the definition of some other function is dependent on another, functors are a good fit.
In the following I only define the less than predicate, but the functor uses that to generate greater than and equal predicates.
# module type COMPARABLE = sig
type t
val lt : t -> t -> bool
end;;
module type COMPARABLE = sig type t val lt : t -> t -> bool end
# module Compare (M : COMPARABLE) = struct
type t = M.t
let lt = M.lt
let gt a b = lt b a
let eq a b = not (lt a b) && not (gt a b)
end;;
module Compare :
functor (M : COMPARABLE) ->
sig
type t = M.t
val lt : t -> t -> bool
val gt : t -> t -> bool
val eq : t -> t -> bool
end
# module A = Compare (struct type t = int let lt a b = a < b end);;
module A :
sig
type t = int
val lt : t -> t -> bool
val gt : t -> t -> bool
val eq : t -> t -> bool
end
# A.(lt 4 5, gt 4 5, eq 4 5);;
- : bool * bool * bool = (true, false, false)
Now, because the first part of the definition of the Compare
functor is just aliasing the contents of the COMPARABLE
module passed to it as M
, we can use include
instead.
# module Compare (M : COMPARABLE) = struct
include M
let gt a b = lt b a
let eq a b = not (lt a b) && not (gt a b)
end;;
module Compare :
functor (M : COMPARABLE) ->
sig
type t = M.t
val lt : t -> t -> bool
val gt : t -> t -> bool
val eq : t -> t -> bool
end
We could carry this further to define ge
and le
functions as well. All based on the less than predicate being defined.
# module Compare (M : COMPARABLE) = struct
include M
let gt a b = lt b a
let eq a b = not (lt a b) && not (gt a b)
let le a b = lt a b || eq a b
let ge a b = gt a b || eq a b
end;;
module Compare :
functor (M : COMPARABLE) ->
sig
type t = M.t
val lt : t -> t -> bool
val gt : t -> t -> bool
val eq : t -> t -> bool
val le : t -> t -> bool
val ge : t -> t -> bool
end