关于类型:具有函子和多态变体的OCaml类型检查问题

OCaml Typechecking Problem With Functors and Polymorphic Variants

我在OCaml中使用函子时遇到问题。我有一个模块类型TASK,该模块类型用于执行各种任务:

1
2
3
4
5
6
7
8
9
module type TASK = sig
  type task_information
  type task_information_as_lists

  type abstract_u_set_type
  module AbstractUSet : Set.S with type t = abstract_u_set_type

  val mk_task_information : task_information_as_lists -> task_information
end

类型为TASK的模块将包含使用节点的算法。这些节点将具有不同的类型。因此,我建立了TASK_NODE

1
2
3
4
5
module type TASK_NODE = sig
  type t
  val compare : t -> t -> int
  val to_string : t -> string
end

TASK中的

task_information_as_lists将是一个包含不同类型的列表,但是每个任务在该列表中将具有不同的类型。因为不能有带函子的之类的东西,所以我创建了一个模块类型INFO_CARRIER。对于每个TASK类型的不同模块,我希望有一个INFO_CARRIER类型的不同模块,该模块将保存task_information_as_lists类型实际上是什么的信息。

这是模块类型INFO_CARRIER

1
2
3
4
module type INFO_CARRIER = sig
  module INODE : TASK_NODE
  type u = [`V of INODE.t list | `E of INODE.t] list
end

为了进行测试,我想拥有一个string TASK_NODES,以及一个可以传达u类型的INFO_CARRIER,例如type u = [`V of string list | `E of string] list

因此我构建了StringTaskNodeStringInfoCarrier,以及一个StringTask以使用节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module StringTaskNode : TASK_NODE = struct
  type t = string
  let compare = compare
  let to_string s ="Node" ^ s
end

module StringInfoCarrier (TN : TASK_NODE) : (INFO_CARRIER with module INODE = TN) = struct
  module INODE = TN
  type u = [`V of TN.t list | `E of TN.t] list
end

module StringTask (TN : TASK_NODE) (IC : INFO_CARRIER with module INODE = TN) :
  (TASK with type task_information_as_lists := IC.u with type abstract_u_set_type := Set.Make(IC.INODE).t) = struct
  module N = IC.INODE
  module AbstractUSet = Set.Make(IC.INODE)

  type task_information = {v_nodes : AbstractUSet.t ; e_nodes : N.t}

  let mk_task_information info_list =
    match info_list with
    | (`V v)::(`E e)::[] -> {v_nodes = AbstractUSet.of_list v ; e_nodes = e;}
    | _ -> raise .... (* raising an error here *)
end

然后我有另一个模块ProdFP,它将为任务做一些计算:

1
2
3
4
5
6
module ProdFP
  (TN : TASK_NODE)
  (IC : INFO_CARRIER with module INODE=TN)
  (TA : TASK with type abstract_u_set_type:=u with type task_information_as_lists:=IC.u) = struct
  ...
end

到目前为止,没有错误发生。但是,当我将所有内容放在Test中时,我得到:

1
2
3
4
5
6
Error: This expression has type
  [`E of string | `V of string list]
but an expression was expected of type
SIC.u = [`E of SIC.INODE.t | `V of SIC.INODE.t list]
Type string is not compatible with type
  SIC.INODE.t = STN.t

这是测试模块:

1
2
3
4
5
6
7
8
9
10
11
12
module Test = struct
  module STN = StringTaskNode
  module SIC = StringInfoCarrier(STN)
  module ST = StringTask(STN)(SIC)
  module PF = ProdFP(STN)(SIC)(ST)

  let v_list =["a";"b"]
  let e ="c"
  let info_as_list = [`V v_list ; `E e]

  let info = ST.mk_task_information info_as_list (* THIS IS WHERE THE ERROR HAPPENS *)
end

我知道,这是一篇很长的文章,但是我尝试添加尽可能多的信息。
如果您能帮助我,那就太好了:)


问题似乎仅仅是StringTaskNode模块定义中的签名约束:

1
2
3
module StringTaskNode : TASK_NODE = struct
...
end

此约束使类型StringTaskNode.t抽象,从而隐藏了等式STN.t = string。删除约束,

1
2
3
module StringTaskNode = struct
...
end

应解决此特定问题。