我在OCaml中遇到类型不兼容的问题。
首先,我有一个文件setBuilder.ml,我在其中定义了一个创建订单的仿函数SO,一个创建集合的仿函数S,以及一个创建包含有用函数的模块的仿函数SM:
module SO (M: sig type t end)
= struct
type t = M.t
let compare = Pervasives.compare
end
module S (P: sig type t end): Set.S with type elt = P.t
= Set.Make (SO (P))
module SM (M: sig type t end):
sig
type t = M.t
module S: Set.S with type elt = t
type set = S.t
...
end
= struct
module S = S (M)
...
end
(在这种情况下,我习惯将这3个模块组合成1个递归模块,但看起来OCaml不允许在参数被排除时创建递归模块(即,当它是一个仿函数时))。
然后在一个名为module_U.ml的不同文件中,我定义了一个模块U,其中函数foo很重要:
module U (M: sig type t end):
sig
module S : Set.S with type elt = M.t
type elt = M.t
type eltSet = S.t
val foo: eltSet -> eltSet -> bool
end
= struct
module S = S (M)
let foo s1 s2 =
...
end
在我的main.ml中,我最终定义了一个包含我将要使用的类型的模块,
module T :
sig
type t=int
end
= struct
type t=int
end
然后我实例化模块SM并获得它的集合S:
module SM = SM (T)
module IntSet = SM.S
然后我实例化模块U并尝试使用它的函数foo:
module U = U (T)
let bar (s1:IntSet.t) (s2:IntSet.t) : bool =
U.foo s1 s2
但我收到错误消息
File "main.ml", line 303, characters 38-39 (which corresponds to s1, in U.foo s1 s2):
Error: This expression has type IntSet.t = setBuilder.SM(T).S.t
but an expression was expected of type
U.eltSet = module_U.U(T).S.t
我不明白,这就是为什么这是一个问题,因为U和SM模块都是用相同的模块T创建的,这意味着创建的两个集合的类型应该是相同的。
如果有人能对此提出任何想法,我将感激不尽。
答案 0 :(得分:2)
尝试使用module S : module type of S(M)
或module S : Set.S with type elt = M.t and type t = S(M).t
。
module S : Set.S with type elt = M.t
的问题在于它不会限制类型S.t