Ocaml 如何满足我的类型

Ocaml 如何满足我的类型,ocaml,Ocaml,我正在尝试为文本创建一个数据类型集(使用Core.Std.set),这样我就可以获得为我的子句类型使用集的性能优势(而不是定义type子句=literal list) 在满足Comparable.S接口部分,我正在关注真实世界的OCaml。问题是我们没有sexp\u of theu t和t\u of theu sexp函数。但是当我将type t=literal行更改为type t=literal with sexp时,编译器会说Error:Unbound value literal\u of_

我正在尝试为文本创建一个数据类型集(使用
Core.Std.set
),这样我就可以获得为我的子句类型使用集的性能优势(而不是定义
type子句=literal list

在满足Comparable.S接口部分,我正在关注真实世界的OCaml。问题是我们没有
sexp\u of theu t
t\u of theu sexp
函数。但是当我将
type t=literal
行更改为
type t=literal with sexp
时,编译器会说
Error:Unbound value literal\u of_sexp


这让我相信(a)我必须自己实现sexp函数(我不确定如何实现),或者(b)无论如何我都不应该试图满足
Comparable.S
(出于某种原因,它只适用于基本类型)。然而,这些函数的实现假定相应的函数可用于
literal
,因为
t
是根据
literal
定义的。换句话说,您还需要将带有sexp的
添加到
type literal=…
,这将反过来要求您对
符号和
原子执行此操作

还请注意,您使用的是camlp4,但许多工具(如您使用的语法扩展)正在迁移到ppx(RWO手册在这一点上已经过时)。建议您现在使用
ppx\u sexp\u conv
支持的
[@@dering sexp]
,而不是使用
sexplib.syntax
支持的

下面是一个完整的工作示例:

$ cat foo.ml
open Core.Std

type atom = string [@@deriving sexp,compare]
type sign = Pos | Neg [@@deriving sexp,compare]
type literal = sign * atom [@@deriving sexp,compare]

module Literal : sig
  type t = literal [@@deriving sexp,compare]
  include Comparable.S with type t := t
end = struct
  module T = struct
    type t = literal [@@deriving sexp,compare]
  end
  include T
  include Comparable.Make(T)
end

module Clause = Set.Make(Literal)
您的
compare
函数非常好,但我还向您展示了如何使用ppx\u compare,它生成
compare
函数。编译如下:

$ ocamlfind ocamlc -package core,ppx_sexp_conv,ppx_compare -thread -c foo.ml

您可以添加
-dsource
以查看生成的代码。您不能按照RWO的建议使用
corebuild
,因为它假定正在使用camlp4,但这与ppx不兼容,因此您将得到一个错误。

首先,您仍然可以使用普通的旧
camlp4
。它并没有被弃用,大多数编译器版本上的大多数核心版本仍然需要它。不要担心,您的代码将依赖于它,当需要时,您可以自动将您的
camlp4
代码转换为
ppx
代码。到目前为止,我建议您坚持使用
camlp4

使用带有
符号的
,您的代码可以重写为:

type atom = string with sexp,compare
type sign = Pos | Neg with sexp,compare
type literal = sign * atom with sexp,compare 

module Literal = struct
  type t = literal with sexp,compare
  include Comparable.Make(struct
      type nonrec t = t with sexp,compare
    end)
end

module Clause = Set.Make(Literal)
但有一件事,你应该知道。无需使用
Set.Make
<代码>可比
界面在内部提供了集合和地图,因此,您应该编写:

module Clause = Literal.Set
还有
Literal.Map
。如果您正在查找哈希表和哈希集,那么您可以使用
Hashable
接口,该接口将为您提供
Literal.Table
Literal.hash\u set
。您可以使用
Hashable.Make
functor实现,并将其结果添加到
Literal
模块:

  include Hashable.Make(struct
      type nonrec t = t with sexp,compare
      let hash = Hashtbl.hash
    end)

您还可以使用
可识别
接口,该接口是
可比较
可散列
的总和

我不会说它不受欢迎。它是基础设施的一项新功能,具有与
camlp4
交叉的功能。后者仍然是一个有价值的工具,到目前为止,它在当前基础架构中有更好的支持,并且适用于我编辑过的所有版本的编译器和核心(不同于
ppx
),以避免暗示camlp4已被弃用。
  include Hashable.Make(struct
      type nonrec t = t with sexp,compare
      let hash = Hashtbl.hash
    end)