生成的折叠类型、迭代器和映射与 ppx_deriving 文档不一致
Type of generated fold, iter and map not coherent with ppx_deriving documentation
我正在努力正确设置我的 OCaml 环境以使用 ppx 派生程序 map、fold 和 iter,如下所示:
https://github.com/ocaml-ppx/ppx_deriving#plugins-iter-map-and-fold
我的最小示例在这里(我正在使用 Base,因为这是我在更广泛的项目中使用的库):
open Base;;
type data = Row of float array | Dim of data array
[@@deriving iter, map, fold, show];;
let t = Row [|2.;2.|];;
pp_data Caml.Format.std_formatter t;;
map_data (fun x -> x +. 1.) t;;
pp_data Caml.Format.std_formatter t;;
以下代码是用
ocamlfind ocamlc -package base -package ppx_deriving.iter -package ppx_deriving.map -package ppx_deriving.fold -package ppx_deriving.show -linkpkg -g test.ml && ./a.out
;我收到一个编译错误,指出 map_data
的类型为 data -> data
。但是根据文档和我的常识, map
得到一个函数和一个可映射的结构,这里似乎不是这样。在 utop 中测试这个给了我同样的错误。
有什么我遗漏的吗?
提前谢谢你:)
这些派生器在多态 数据结构上工作,并将用户函数应用于与该结构的类型变量对应的所有值。由于您没有任何类型变量,因此生成的 map_data
函数有缺陷,但很自然,因为缺少类型变量意味着函数是常量。
换句话说,map_x
函数的一般结构对于某些具有 N
类型变量的多态 type ('s1, ..., 'sN) x
是
('s1 -> 't1) -> ... -> ('sN -> 'tN) -> ('s1,...,'sN) x -> ('t1,...,'tN) x
即,对于每个类型变量,它需要一个函数将该类型的值映射到其他类型,以便映射函数的参数数量为 N+1
在您的情况下,因为您有零类型变量, 没有映射函数所以你只有 x -> x
.
如果您将类型重新定义为
type 'a data = Row of 'a array | Dim of 'a data array
[@@deriving iter, map, fold, show]
您将获得 map_data
,预期类型为 ('a -> 'b) -> 'a data -> 'b data
。推导者甚至会理解数组是一种数据结构并对其进行递归,例如,
let input = Dim [|Row [|1;2;3|]; Row [|3;4;5|]|]
map_data (fun x -> x + 1) input;;
- : int data = Dim [|Row [|2; 3; 4|]; Row [|4; 5; 6|]|]
当然,如果你不想在你的接口中使用多态类型,你总是可以创建一个类型别名,例如,
type t = float data
并将 map_data 公开为
val map_data : (float -> float) -> t -> t
我正在努力正确设置我的 OCaml 环境以使用 ppx 派生程序 map、fold 和 iter,如下所示: https://github.com/ocaml-ppx/ppx_deriving#plugins-iter-map-and-fold
我的最小示例在这里(我正在使用 Base,因为这是我在更广泛的项目中使用的库):
open Base;;
type data = Row of float array | Dim of data array
[@@deriving iter, map, fold, show];;
let t = Row [|2.;2.|];;
pp_data Caml.Format.std_formatter t;;
map_data (fun x -> x +. 1.) t;;
pp_data Caml.Format.std_formatter t;;
以下代码是用
ocamlfind ocamlc -package base -package ppx_deriving.iter -package ppx_deriving.map -package ppx_deriving.fold -package ppx_deriving.show -linkpkg -g test.ml && ./a.out
;我收到一个编译错误,指出 map_data
的类型为 data -> data
。但是根据文档和我的常识, map
得到一个函数和一个可映射的结构,这里似乎不是这样。在 utop 中测试这个给了我同样的错误。
有什么我遗漏的吗?
提前谢谢你:)
这些派生器在多态 数据结构上工作,并将用户函数应用于与该结构的类型变量对应的所有值。由于您没有任何类型变量,因此生成的 map_data
函数有缺陷,但很自然,因为缺少类型变量意味着函数是常量。
换句话说,map_x
函数的一般结构对于某些具有 N
类型变量的多态 type ('s1, ..., 'sN) x
是
('s1 -> 't1) -> ... -> ('sN -> 'tN) -> ('s1,...,'sN) x -> ('t1,...,'tN) x
即,对于每个类型变量,它需要一个函数将该类型的值映射到其他类型,以便映射函数的参数数量为 N+1
在您的情况下,因为您有零类型变量, 没有映射函数所以你只有 x -> x
.
如果您将类型重新定义为
type 'a data = Row of 'a array | Dim of 'a data array
[@@deriving iter, map, fold, show]
您将获得 map_data
,预期类型为 ('a -> 'b) -> 'a data -> 'b data
。推导者甚至会理解数组是一种数据结构并对其进行递归,例如,
let input = Dim [|Row [|1;2;3|]; Row [|3;4;5|]|]
map_data (fun x -> x + 1) input;;
- : int data = Dim [|Row [|2; 3; 4|]; Row [|4; 5; 6|]|]
当然,如果你不想在你的接口中使用多态类型,你总是可以创建一个类型别名,例如,
type t = float data
并将 map_data 公开为
val map_data : (float -> float) -> t -> t