jrk*_*jrk 6 ocaml s-expression
Sexplib的语法扩展使得OCaml中的任意用户定义数据结构的序列化和反序列化变得容易.通常通过with sexp在类型定义的末尾添加注释来完成:
type a = A of int | B of float with sexp
Run Code Online (Sandbox Code Playgroud)
这似乎不直接推广到基于仿函数的类型,也不清楚Sexplib标准类型转换器如何捕获甚至标准仿函数.
到目前为止,我已经通过int Map.Make(String).t在序列化之前将特定的Map类型实例(例如)展平到列表来解决这个问题,反之亦然,但是肯定这一点并没有完全被Sexplib/Jane Street Core的雄心勃勃的作者所忽视.我还注意到旧版本的电池在自定义性别序列化中混合了它们的主要模块,如[Bat] Map,但这已被删除了一段时间.
如何使用Sexplib序列化常用的地图或其他复杂仿函数类型?
一种方法是定义一个新函子,它接受序列化数据所需的附加信息。这是我过去使用电池的完整实现。请注意,我还更喜欢无异常且带标签的地图版本,因此我已打开它们,但您当然可以将其删除。
module type SEXPABLE = sig
type t
val sexp_of_t : t -> Sexplib.Sexp.t
val t_of_sexp : Sexplib.Sexp.t -> t
end
module Map = struct
module type S = sig
include BatMap.S
include module type of Labels
include module type of Exceptionless
val sexp_of_t : ('a -> Sexplib.Sexp.t) -> 'a t -> Sexplib.Sexp.t
val t_of_sexp : (Sexplib.Sexp.t -> 'a) -> Sexplib.Sexp.t -> 'a t
end
module Make (Ord : BatInterfaces.OrderedType)
(Sexpable : SEXPABLE with type t = Ord.t)
: S with type key = Ord.t = struct
include BatMap.Make(Ord)
include Labels
include Exceptionless
open Sexplib.Sexp
open Sexplib.Conv
let sexp_of_t sexp_of_data t =
let f ~key ~data ans = List [Sexpable.sexp_of_t key; sexp_of_data data] :: ans in
List (fold ~f ~init:[] t)
let t_of_sexp data_of_sexp sexp = match sexp with
| Atom _ -> of_sexp_error "Map.Make(...).t_of_sexp: list needed" sexp
| List l ->
let f ans = function
| List [key_sexp; data_sexp] ->
let key = Sexpable.t_of_sexp key_sexp in
let data = data_of_sexp data_sexp in
add ~key ~data ans
| List _ | Atom _ ->
of_sexp_error "Map.Make(...).t_of_sexp: 2-tuple list needed" sexp
in
List.fold_left ~f ~init:empty l
end
end
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,电池删除了这些功能以减少对其他库的依赖。您的另一个选择是使用 Core,它具有开箱即用的这些功能。