OCaml 中的函子

发布于 2024-07-14 19:03:23 字数 1508 浏览 4 评论 0原文

我在函子(及其结果类型)方面遇到了一些问题。 下面,我有一个使用 Ordered 类型的 Set 函子。 我实际上使用了 OCaml 附带的 set.ml 来获取一些指导,但我似乎一切都做对了。 我创建了一个包含整数的 Ordered 模块,并将其应用于 Set 函子,以获取此代码示例中的最后一个模块 IntSet

当我尝试插入整数时,下一行失败。 我收到以下类型错误:

Error: This expression has type int but is here used with type
         SetInt.elt = Set(OrdInt).elt

不要误会我的意思,这里的类型系统是正确的。 顶层报告 SetInt.elt 的类型是 Set(OrdInt).elt,但是当我使用提供的操作执行相同操作来设置 Set 时根据 OCaml,“同一”行是 SetInt.elt = OrderedInt.t。 看来我应该得到 SetInt.elt = Ordered.t

这很简单,我可能只是错过了一些愚蠢的细节! 啊!

请注意:我在这里简化了成员/插入函数,因为这个问题与类型有关。

module type Ordered =
  sig
    type t 
    val lt : t -> t -> bool
    val eq : t -> t -> bool
    val leq : t -> t -> bool
  end

module type S =
  sig
    type elt
    type t
    exception Already_Exists
    val empty  : t
    val insert : elt -> t -> t
    val member : elt -> t -> bool
  end

module Set (Elt:Ordered) : S = 
  struct
    type elt = Elt.t
    type t = Leaf | Node of t * elt * t
    exception Already_Exists
    let empty = Leaf
    let insert e t = t
    let member e t = false
  end

module OrdInt : Ordered =
  struct
    type t = int
    let lt a b = a < b
    let eq a b = a = b
    let leq a b = a <= b
  end

module IntSet = Set (OrdInt)

(* line that fails *)
let one_elm = IntSet.insert 1 IntSet.empty

I am having a bit of a problem with a functor (and it's resultant type). Below, I have a Set functor that uses an Ordered type. I actually used the set.ml that comes with OCaml for some guidance, but I seem to be doing everything ahem right. I created an Ordered module with integers and applied it to the Set functor to get the last module on this code sample, IntSet.

The next line fails, when I try to insert an integer. I get the following type error:

Error: This expression has type int but is here used with type
         SetInt.elt = Set(OrdInt).elt

Don't get me wrong, the type system is correct here. The top level reports that the type of the SetInt.elt is Set(OrdInt).elt, but when I do the same operations to set up a Set using the one provided by OCaml the 'same' line is, SetInt.elt = OrderedInt.t. Seems like I should be getting SetInt.elt = Ordered.t.

This is so simple, I'm probably just missing some stupid detail! argh!

Please Note: I have simplified the member/insert functions here since this issue has to do with types.

module type Ordered =
  sig
    type t 
    val lt : t -> t -> bool
    val eq : t -> t -> bool
    val leq : t -> t -> bool
  end

module type S =
  sig
    type elt
    type t
    exception Already_Exists
    val empty  : t
    val insert : elt -> t -> t
    val member : elt -> t -> bool
  end

module Set (Elt:Ordered) : S = 
  struct
    type elt = Elt.t
    type t = Leaf | Node of t * elt * t
    exception Already_Exists
    let empty = Leaf
    let insert e t = t
    let member e t = false
  end

module OrdInt : Ordered =
  struct
    type t = int
    let lt a b = a < b
    let eq a b = a = b
    let leq a b = a <= b
  end

module IntSet = Set (OrdInt)

(* line that fails *)
let one_elm = IntSet.insert 1 IntSet.empty

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

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

发布评论

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

评论(1

风启觞 2024-07-21 19:03:23

您需要将这两行更改

module Set (Elt:Ordered) : S = 
module OrdInt : Ordered =

module Set (Elt:Ordered) : S with type elt = Elt.t = 
module OrdInt : Ordered with type t = int =

如果没有这些,模块将不会具有将类型 elt 和 t 公开为 int 的签名。

[编辑]:
set.ml 没有“with”位,因为有一个 sml.mli,它声明函子的签名并且它确实有“with”。 此外,如果您没有显式为其指定签名,则 OrdInt 不需要“with”,如下所示:

module OrdInt =

您还可以通过就地定义模块来构造集合:

module IntSet = Set (struct
 type t = int
 let lt a b = a < b
 let eq a b = a = b
 let leq a b = a <= b
end) 

You need to change these two lines

module Set (Elt:Ordered) : S = 
module OrdInt : Ordered =

to

module Set (Elt:Ordered) : S with type elt = Elt.t = 
module OrdInt : Ordered with type t = int =

Without these, the modules will not have signatures that expose the types elt and t as int.

[Edit]:
The set.ml doesn't have the 'with' bit, because there's a sml.mli, which declares the signature for the functor and it does have the 'with'. Also, OrdInt doesn't need 'with' if you don't explicitly specify a signature for it, like this:

module OrdInt =

You can also construct the set by defining the module in place:

module IntSet = Set (struct
 type t = int
 let lt a b = a < b
 let eq a b = a = b
 let leq a b = a <= b
end) 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文