I am having a bit of a problem with a functor (and it’s resultant type). Below, I have a Set functor that uses an Ordered type. I actually used the set.ml that comes with OCaml for some guidance, but I seem to be doing everything ahem right. I created an Ordered module with integers and applied it to the Set functor to get the last module on this code sample, IntSet.
The next line fails, when I try to insert an integer. I get the following type error:
Error: This expression has type int but is here used with type SetInt.elt = Set(OrdInt).elt
Don’t get me wrong, the type system is correct here. The top level reports that the type of the SetInt.elt is Set(OrdInt).elt, but when I do the same operations to set up a Set using the one provided by OCaml the ‘same’ line is, SetInt.elt = OrderedInt.t. Seems like I should be getting SetInt.elt = Ordered.t.
This is so simple, I’m probably just missing some stupid detail! argh!
Please Note: I have simplified the member/insert functions here since this issue has to do with types.
module type Ordered = sig type t val lt : t -> t -> bool val eq : t -> t -> bool val leq : t -> t -> bool end module type S = sig type elt type t exception Already_Exists val empty : t val insert : elt -> t -> t val member : elt -> t -> bool end module Set (Elt:Ordered) : S = struct type elt = Elt.t type t = Leaf | Node of t * elt * t exception Already_Exists let empty = Leaf let insert e t = t let member e t = false end module OrdInt : Ordered = struct type t = int let lt a b = a < b let eq a b = a = b let leq a b = a <= b end module IntSet = Set (OrdInt) (* line that fails *) let one_elm = IntSet.insert 1 IntSet.empty
You need to change these two lines
to
Without these, the modules will not have signatures that expose the types elt and t as int.
[Edit]: The set.ml doesn’t have the ‘with’ bit, because there’s a sml.mli, which declares the signature for the functor and it does have the ‘with’. Also, OrdInt doesn’t need ‘with’ if you don’t explicitly specify a signature for it, like this:
You can also construct the set by defining the module in place: