理解 OCaml 中的函子
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
(您发布不可编译的代码。这是一个坏主意,因为它可能会让人们更难帮助您,而且因为将问题简化为一个简单的示例有时足以解决它。但我想我无论如何都看到了您的困难。 )
在
formulas.ml
中,Ocaml 可以看到PrismPctl.s = Pctl.Make(Prism).t = Prism.t
;第一个等式来自于PrismPctl
的定义,第二个等式来自于Pctl.Make
的签名(特别是类型 s = Pt 的> 位)。
如果您没有为
Formulas
编写mli
文件,您的代码应该可以编译。所以问题一定是您编写的 .mli 文件没有提到正确的相等性。您没有显示您的.mli
文件(您应该这样做,它们是问题的一部分),但大概您写了“这还不够:当编译器编译
main.ml,它不会了解
formulas.mli
中未指定的任何有关PrismPctl
的信息。您需要指定或,假设您在
pctl.mli
的Make
签名中包含了with type s = Pt
(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 thatPrismPctl.s = Pctl.Make(Prism).t = Prism.t
; the first equality is from the definition ofPrismPctl
, and the second equality is from the signature ofPctl.Make
(specifically thewith type s = P.t
bit).If you don't write an
mli
file forFormulas
, 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 wroteThat's not enough: when the compiler compiles
main.ml
, it won't know anything aboutPrismPctl
that's not specified informulas.mli
. You need to specify eitheror, assuming you included
with type s = P.t
in the signature ofMake
inpctl.mli
这也是我在了解更多相关知识时遇到的问题。创建函子时,您会公开函子的签名,在本例中为
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 types
, parameterized by the functor, and anything more specific is not exposed to the outside. Thus, accessing any record element ofs
(as insys_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.