8

我对 OCaml 中的以下仿函数问题非常困扰。我粘贴一些代码只是为了让您理解。基本上

我在以下位置定义了这两个模块pctl.ml

module type ProbPA = sig
  include Hashtbl.HashedType  
  val next: t -> (t * float) list
  val print: t -> float -> unit
end

module type M = sig
  type s  
  val set_error: float -> unit
  val check: s -> formula -> bool
  val check_path: s -> path_formula -> float
  val check_suite: s -> suite -> unit
end

和以下函子:

module Make(P: ProbPA): (M with type s = P.t) = struct
  type s = P.t
  (* implementation *)
end

然后为了实际使用这些模块,我直接在一个名为的文件中定义了一个新模块prism.ml

type state = value array
type t = state
type value =
  | VBOOL of bool
  | VINT of int
  | VFLOAT of float
  | VUNSET
(* all the functions required *)

从第三个来源( )我使用了带有模块formulas.ml的函子:Prism

module PrismPctl = Pctl.Make(Prism)
open PrismPctl

最后从main.ml

open Formulas.PrismPctl
(* code to prepare the object *)
PrismPctl.check_suite s.sys_state suite (* error here *)

并编译给出以下错误

错误:此表达式的类型为 Prism.state = Prism.value 数组,但表达式应为 Formulas.PrismPctl.s 类型

据我所知,名称有一种不好的别名,它们是相同的(因为value array类型定义为t并且M with type s = P.t在仿函数中使用)但类型检查器不认为它们相同。

我真的不明白问题出在哪里,有人可以帮助我吗?

提前致谢

4

2 回答 2

6

(您发布了不可编译的代码。这是一个坏主意,因为它可能会使人们更难帮助您,并且因为将您的问题简化为一个简单的示例有时足以解决它。但我想我还是看到了您的困难。 )

在里面formulas.ml,Ocaml 可以看到PrismPctl.s = Pctl.Make(Prism).t = Prism.t;第一个等式来自 的定义PrismPctl,第二个等式来自Pctl.Make(特别是with type s = P.t位)的签名。

如果您不为 编写mli文件Formulas,您的代码应该可以编译。所以问题一定是.mli你写的文件没有提到正确的相等性。你不显示你的.mli文件(你应该,它们是问题的一部分),但大概你写了

module PrismPctl : Pctl.M

这还不够:当编译器编译时,它不会main.ml知道. 您需要指定PrismPctlformulas.mli

module PrismPctl : Pctl.M with type s = Prism.t

或者,假设您包含with type s = P.t在 in 的签名Makepctl.mli

module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s
于 2010-07-25T19:37:32.017 回答
2

这也是我在了解更多有关这些内容时遇到的问题。当您创建仿函数时,您会公开仿函数的签名,在本例中为M. 它包含一个s由函子参数化的抽象类型,并且任何更具体的内容都不会暴露给外部。因此,访问s(as in sys_state) 的任何记录元素都会导致类型错误,正如您所遇到的那样。

其余的看起来还不错。正确使用仿函数肯定很难,但请记住,您只能通过仿函数公开的接口/签名来操作仿函数参数化类型的实例。

于 2010-07-25T06:21:29.680 回答