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
A signature specifies which components of a structure are accessible from the outside, and with which type. It can be used to hide some components of a structure (e.g. local function definitions) or export some components with a restricted type.
In OCaml, every piece of code is wrapped into a module. Optionally, a module itself can be a submodule of another module, pretty much like directories in a file system - but we don't do this very often.
As you noticed, F# doesn't have functors - F# modules cannot be parameterized by types. You can get similar results in F# using the object oriented parts of the language - interfaces, generic classes and inheritance.
You need to change these two lines
module Set (Elt:Ordered) : S =
module OrdInt : Ordered =
to
module Set (Elt:Ordered) : S with type elt = Elt.t =
module OrdInt : Ordered with type t = int =
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:
module OrdInt =
You can also construct the set by defining the module in place:
module IntSet = Set (struct
type t = int
let lt a b = a < b
let eq a b = a = b
let leq a b = a <= b
end)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With