我正在尝试使用ocamlc编译以下代码。
type 'a splitter = {name: string; decision_function : 'a -> bool}
let splitter12a = {name="x1>x2"; decision_function=(fun x -> x.(1)>x.(2))};;
let generate_splitter i j = {name="x"^string_of_int(i)^">x"^string_of_int(j); decision_function=(fun x -> x.(i) > x.(j))} ;;
let splitter12 = generate_splitter 1 2;;
然而,编译器抱怨:
File "error.ml", line 7, characters 17-38:
Error: The type of this expression, '_a array splitter,
contains type variables that cannot be generalized
我不明白为什么我可以声明专门的splitter12a
,而generate_splitter
无法生成专门的分割器。
答案 0 :(得分:1)
您遇到了所谓的值限制。有关说明,请参阅例如真实世界Ocaml的this chapter中相同标题的部分。
编辑:通常的工作(可能在该章中提出)是 eta扩展,意思是展开一个lambda,例如,将定义let f = g a
转换为let f x = g a x
}。但这不适用于您的情况,因为您的def的RHS不会产生功能。对于你想做的事情,确实没有直接的解决方法。
一种方法是将其变成仿函数:
module MakeSplitter (X : sig val i : int val j : int end) =
struct
let splitter = {name = "x"^string_of_int(i)^">x"^string_of_int(j); decision_function = fun x -> x.(i) > x.(j)}
end
module Splitter12 = MakeSplitter(struct val i = 1 val j = 2 end)
let splitter12 = Splitter12.splitter
另一种方法是使用带有多态字段的辅助记录类型,与上面的结构非常相似。