函子和多态变体的 OCaml 类型检查问题
OCaml Typechecking Problem With Functors and Polymorphic Variants
我在 OCaml 中使用仿函数时遇到问题。我有一个模块类型 TASK
用于执行不同类型的任务:
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
:
module type TASK_NODE = sig
type t
val compare : t -> t -> int
val to_string : t -> string
end
TASK
中的 task_information_as_lists
将是一个包含不同类型的列表,但每个任务在该列表中都有不同的类型。因为我不能用仿函数来使用 module Game : (TASK with with type u := int list)
之类的东西,所以我创建了一个模块类型 INFO_CARRIER
。对于 TASK
类型的每个不同模块,我想要一个 INFO_CARRIER
类型的不同模块,它将保存 task_information_as_lists
实际是什么类型的信息。
这是模块类型INFO_CARRIER
:
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
和一个 INFO_CARRIER
可以传达像 type u = [`V of string list | `E of string] list
这样的类型 u。
所以我构建了 StringTaskNode
和 StringInfoCarrier
,还有一个 StringTask
来使用节点:
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
将为任务做一些计算:
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
中时,我得到:
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
这是测试模块:
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
我知道,这是一篇很长的文章 post,但我已尽力包含尽可能多的信息。
如果你能帮助我,那就太好了:)
看起来问题只是 StringTaskNode
模块定义中的签名约束:
module StringTaskNode : TASK_NODE = struct
...
end
此约束使类型 StringTaskNode.t
抽象,从而隐藏了等式 STN.t = string
。删除约束,
module StringTaskNode = struct
...
end
应该可以解决这个具体问题。
我在 OCaml 中使用仿函数时遇到问题。我有一个模块类型 TASK
用于执行不同类型的任务:
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
:
module type TASK_NODE = sig
type t
val compare : t -> t -> int
val to_string : t -> string
end
TASK
中的 task_information_as_lists
将是一个包含不同类型的列表,但每个任务在该列表中都有不同的类型。因为我不能用仿函数来使用 module Game : (TASK with with type u := int list)
之类的东西,所以我创建了一个模块类型 INFO_CARRIER
。对于 TASK
类型的每个不同模块,我想要一个 INFO_CARRIER
类型的不同模块,它将保存 task_information_as_lists
实际是什么类型的信息。
这是模块类型INFO_CARRIER
:
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
和一个 INFO_CARRIER
可以传达像 type u = [`V of string list | `E of string] list
这样的类型 u。
所以我构建了 StringTaskNode
和 StringInfoCarrier
,还有一个 StringTask
来使用节点:
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
将为任务做一些计算:
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
中时,我得到:
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
这是测试模块:
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
我知道,这是一篇很长的文章 post,但我已尽力包含尽可能多的信息。 如果你能帮助我,那就太好了:)
看起来问题只是 StringTaskNode
模块定义中的签名约束:
module StringTaskNode : TASK_NODE = struct
...
end
此约束使类型 StringTaskNode.t
抽象,从而隐藏了等式 STN.t = string
。删除约束,
module StringTaskNode = struct
...
end
应该可以解决这个具体问题。