2015-11-21 34 views
0

我想爲我的數據類型設置一個字符集(使用Core.Std.Set),以便我可以使用我的子句類型集的性能優勢(而不是定義type clause = literal list )。如何滿足Comparable.S與我的類型

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) 

我是在下真實世界的OCaml,Chapter 13. Maps and Hash Tables通過滿足Comparable.S接口部分。問題是我們沒有sexp_of_tt_of_sexp函數。但是當我將type t = literal行更改爲type t = literal with sexp時,編譯器會說Error: Unbound value literal_of_sexp。 (a)我必須自己執行sexp函數(我不知道我該如何處理這個問題),或者(b)我不應該試圖滿足Comparable.S(無論如何,我不應該試圖滿足Comparable.S)由於某種原因,只能用於原始類型)。

回答

1

首先,你仍然可以使用普通老camlp4。它不被棄用,大多數編譯器版本的核心版本仍然需要它。並且不要害怕,您的代碼將取決於它,需要時您可以自動將您的camlp4代碼翻譯爲ppx代碼。到目前爲止,我會建議你堅持camlp4

使用with符號,你的代碼可以改寫爲:

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.MakeComparable接口提供集和映射裏面,所以,你應該寫:

module Clause = Literal.Set 

還有Literal.Map。如果你正在尋找散列表和散列集,那麼你的界面就是,那會給你Literal.TableLiteral.Hash_set。您可以實現使用Hashable.Make函子,並增加其結果的Literal模塊:

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

您也可以使用Identifiable界面是ComparableHashable的總和。

1

書寫type t = literal with sexp請求生成t的函數,這將是t_of_sexpsexp_of_t。但是,這些函數的實現假定相應的函數可用於literal,因爲t根據literal定義。換句話說,您還需要將with sexp添加到type literal = ...,這又要求您爲sign和​​這樣做。

另請注意,您正在使用camlp4,但許多工具(如您正在使用的語法擴展名)正在遷移到ppx(RWO書籍在這一點上已過時)。我們鼓勵您在ppx_sexp_conv的支持下做[@@deriving sexp],而不是with 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_compare,產生compare功能。編譯如下:

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

您可以添加-dsource來查看生成的代碼。 RWO建議您不能使用corebuild,因爲它假定正在使用camlp4,但與ppx不兼容,所以會出現錯誤。

+0

我不會說它已被棄用。這是基礎設施的一項新功能,它與'camlp4'具有交叉功能。後者仍然是一個有價值的工具,迄今爲止在當前的基礎架構中有更好的支持,並且適用於所有版本的編譯器和核心(與'ppx'不同)' – ivg

+0

我編輯過,以避免提示camlp4已被棄用。 –