如何满足Comparable.S与我的类型

时间:2015-11-21 15:21:38

标签: ocaml

我正在尝试为我的数据类型创建一个(使用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_tt_of_sexp函数。但是当我将type t = literal行更改为type t = literal with sexp时,编译器会说Error: Unbound value literal_of_sexp

这让我相信(a)我必须自己实施sexp功能(我不确定我是如何处理这个),或者(b)我不应该试图满足{{1}无论如何(出于某种原因,它只适用于原始类型)。

1 个答案:

答案 0 :(得分:1)

撰写type t = literal with sexp次请求以生成t的函数,t_of_sexpsexp_of_t。但是,这些函数的实现假设literal可以使用相应的函数,因为t是根据literal定义的。换句话说,您还需要将with sexp添加到type literal = ...,这反过来要求您对signatom执行此操作。

另请注意,您使用的是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不兼容,因此您将收到错误。