.ml 文件中定义的模块如何引用自身
How can a module defined in a .ml file reference itself
我正在尝试定义一个 Point
模块,它定义了一个表示 2d 点的类型。
我还想包含一个子模块 Point.Set
以便 Point.Set.t
一个类型,意思是 'a set of Points'。这似乎合乎逻辑且方便,但我无法弄清楚如何制作这涉及的 'circular' 参考。
我试过这个:
文件:point.ml(隐式定义了一个'Point'模块)
type t = {x: int; y:int}
let compare {x=x1;y=y1} {x=x2;y=y2} = ...implementation omitted for brevity...
module Set = Stdlib.Set.Make(Point)
(* ^^^^^ Internal path Mylib__Point is dangling *)
当我 dune build
Mylib
project/library 时,我得到一个错误:
Internal path Mylib__Point is dangling.
The compiled interface for module Mylib__Point was not found.
我不完全确定错误的真正含义,但我认为它可能与我们试图引用 Point
模块本身。也许这是不允许的?
我可以通过定义一个单独的 'pointSet.ml' 文件来解决这个问题,其中有 include Set.Make(Point)
。现在我有一个名为 PointSet
的模块。没关系,但如果 Point.Set
可以是 Point
的子模块,我仍然会发现它 'aesthetically pleasing' 多一点。有没有办法让这个工作?
据我所知,模块本身没有名称。你可以制作一个模块(一个结构)只是为了将它提供给仿函数 Set.Make:
type t = { x : int; y : int }
let compare a b = compare a b
module Set =
Set.Make(struct type nonrec t = t let compare = compare end)
如果您不介意一些样板文件,我认为这个解决方案可能适合您:
point.ml
module Point = struct
type t = { x : int; y : int }
let compare { x = x1; y = _y1 } { x = x2; y = _y2 } = x1 - x2
end
module Set : Set.S with type elt = Point.t = Set.Make (Point)
include Point
您将可以访问 Point.Set
,并且由于 point.ml
在文件末尾包含模块 Point
,因此您不必执行 Point.Point.compare ...
在其他文件中。
[编辑]
我之前让模块相互递归,但在这种情况下它没用。如果你需要它们相互递归,你必须明确它们的签名:
point.ml
module rec Point : sig
type t
val compare : t -> t -> int
end = struct
type t = { x : int; y : int }
let compare { x = x1; y = _y1 } { x = x2; y = _y2 } = x1 - x2
end
and Set : (Stdlib.Set.S with type elt = Point.t) = Stdlib.Set.Make (Point)
include Point
我正在尝试定义一个 Point
模块,它定义了一个表示 2d 点的类型。
我还想包含一个子模块 Point.Set
以便 Point.Set.t
一个类型,意思是 'a set of Points'。这似乎合乎逻辑且方便,但我无法弄清楚如何制作这涉及的 'circular' 参考。
我试过这个:
文件:point.ml(隐式定义了一个'Point'模块)
type t = {x: int; y:int}
let compare {x=x1;y=y1} {x=x2;y=y2} = ...implementation omitted for brevity...
module Set = Stdlib.Set.Make(Point)
(* ^^^^^ Internal path Mylib__Point is dangling *)
当我 dune build
Mylib
project/library 时,我得到一个错误:
Internal path Mylib__Point is dangling.
The compiled interface for module Mylib__Point was not found.
我不完全确定错误的真正含义,但我认为它可能与我们试图引用 Point
模块本身。也许这是不允许的?
我可以通过定义一个单独的 'pointSet.ml' 文件来解决这个问题,其中有 include Set.Make(Point)
。现在我有一个名为 PointSet
的模块。没关系,但如果 Point.Set
可以是 Point
的子模块,我仍然会发现它 'aesthetically pleasing' 多一点。有没有办法让这个工作?
据我所知,模块本身没有名称。你可以制作一个模块(一个结构)只是为了将它提供给仿函数 Set.Make:
type t = { x : int; y : int }
let compare a b = compare a b
module Set =
Set.Make(struct type nonrec t = t let compare = compare end)
如果您不介意一些样板文件,我认为这个解决方案可能适合您:
point.ml
module Point = struct
type t = { x : int; y : int }
let compare { x = x1; y = _y1 } { x = x2; y = _y2 } = x1 - x2
end
module Set : Set.S with type elt = Point.t = Set.Make (Point)
include Point
您将可以访问 Point.Set
,并且由于 point.ml
在文件末尾包含模块 Point
,因此您不必执行 Point.Point.compare ...
在其他文件中。
[编辑]
我之前让模块相互递归,但在这种情况下它没用。如果你需要它们相互递归,你必须明确它们的签名:
point.ml
module rec Point : sig
type t
val compare : t -> t -> int
end = struct
type t = { x : int; y : int }
let compare { x = x1; y = _y1 } { x = x2; y = _y2 } = x1 - x2
end
and Set : (Stdlib.Set.S with type elt = Point.t) = Stdlib.Set.Make (Point)
include Point