理解 OCaml 中的函子

发布于 2024-09-11 19:04:05 字数 1454 浏览 6 评论 0原文

我在 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 和类型 s = Pt),但类型检查器并不认为它们是相同的。

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

提前致谢

I'm quite stuck with the following functor problem in OCaml. I paste some of the code just to let you understand. Basically

I defined these two modules in 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

and the following functor:

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

Then to actually use these modules I defined a new module directly in a file called 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 *)

From a third source (formulas.ml) I used the functor with Prism module:

module PrismPctl = Pctl.Make(Prism)
open PrismPctl

And finally from main.ml

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

and compiles gives the following error

Error: This expression has type Prism.state = Prism.value array
but an expression was expected of type Formulas.PrismPctl.s

From what I can understand there a sort of bad aliasing of the names, they are the same (since value array is the type defined as t and it's used M with type s = P.t in the functor) but the type checker doesn't consider them the same.

I really don't understand where is the problem, can anyone help me?

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

弱骨蛰伏 2024-09-18 19:04:05

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

formulas.ml 中,Ocaml 可以看到 PrismPctl.s = Pctl.Make(Prism).t = Prism.t;第一个等式来自于 PrismPctl 的定义,第二个等式来自于 Pctl.Make 的签名(特别是类型 s = Pt 的 > 位)。

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

module PrismPctl : Pctl.M

这还不够:当编译器编译 main.ml,它不会了解 formulas.mli 中未指定的任何有关 PrismPctl 的信息。您需要指定

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

或,假设您在 pctl.mliMake 签名中包含了 with type s = Pt

module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s

(You post non-compilable code. That's a bad idea because it may make it harder for people to help you, and because reducing your problem down to a simple example is sometimes enough to solve it. But I think I see your difficulty anyway.)

Inside formulas.ml, Ocaml can see that PrismPctl.s = Pctl.Make(Prism).t = Prism.t; the first equality is from the definition of PrismPctl, and the second equality is from the signature of Pctl.Make (specifically the with type s = P.t bit).

If you don't write an mli file for Formulas, your code should compile. So the problem must be that the .mli file you wrote doesn't mention the right equality. You don't show your .mli files (you should, they're part of the problem), but presumably you wrote

module PrismPctl : Pctl.M

That's not enough: when the compiler compiles main.ml, it won't know anything about PrismPctl that's not specified in formulas.mli. You need to specify either

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

or, assuming you included with type s = P.t in the signature of Make in pctl.mli

module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s
小鸟爱天空丶 2024-09-18 19:04:05

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

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

This is a problem I ran into as well when learning more about these. When you create the functor you expose the signature of the functor, in this case M. It contains an abstract type s, parameterized by the functor, and anything more specific is not exposed to the outside. Thus, accessing any record element of s (as in sys_state) will result in a type error, as you've encountered.

The rest looks alright. It is definitely hard to get into using functors properly, but remember that you can only manipulate instances of the type parameterized by the functor through the interface/signature being exposed by the functor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文