我正在尝试为我的数据类型创建一个(使用Core.Std.Set
)我的数据类型的集合,这样我就可以获得为我的子句类型使用集合的性能优势(而不是定义type clause = literal list
)
type atom = string
type sign = Pos | Neg
type literal = sign * atom
module Literal : sig
type t = literal
include Comparable.S with type t := t
end = struct
module T = struct
type t = literal
let compare t1 t2 =
match (t1,t2) with
| ((Pos,_), (Neg,_)) -> 1
| ((Neg,_), (Pos,_)) -> -1
| ((_,x), (_,y)) -> String.compare x y
end
include T
include Comparable.Make(T)
end
module Clause = Set.Make(Literal)
我在满足Comparable.S接口部分关注了Real World OCaml,Chapter 13. Maps and Hash Tables。问题是我们没有sexp_of_t
和t_of_sexp
函数。但是当我将type t = literal
行更改为type t = literal with sexp
时,编译器会说Error: Unbound value literal_of_sexp
。
这让我相信(a)我必须自己实施sexp功能(我不确定我是如何处理这个),或者(b)我不应该试图满足{{1}无论如何(出于某种原因,它只适用于原始类型)。
答案 0 :(得分:1)
撰写type t = literal with sexp
次请求以生成t
的函数,t_of_sexp
和sexp_of_t
。但是,这些函数的实现假设literal
可以使用相应的函数,因为t
是根据literal
定义的。换句话说,您还需要将with sexp
添加到type literal = ...
,这反过来要求您对sign
和atom
执行此操作。
另请注意,您使用的是camlp4,但许多工具(例如您正在使用的语法扩展名)正在迁移到ppx(此时RWO书已过时)。我们鼓励您with sexp
支持sexplib.syntax
,而不是[@@deriving sexp]
支持ppx_sexp_conv
。
这是一个完整的工作示例:
$ 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_compare,它会生成compare
个函数。编译如下:
$ ocamlfind ocamlc -package core,ppx_sexp_conv,ppx_compare -thread -c foo.ml
您可以添加-dsource
来查看生成的代码。您不能使用corebuild
作为RWO推荐的,因为它假设正在使用camlp4,但这与ppx不兼容,因此您将收到错误。