2017-01-22 103 views
1

我想用ocamlc编译下面的代码。OCaml变量类型泛化

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 

我不明白为什么我可以宣布一个专门splitter12agenerate_splitter不能生成专门的分离器。

回答

1

您遇到了所谓的值限制。有关说明,请参阅真实世界Ocaml的this chapter中同一标题的部分。

编辑:通常围绕工作(可能是在该章中所建议的)是ETA膨胀,意思是扩大了一个拉姆达,例如,通过转动一个定义let f = g alet 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 

另一种方法是使用辅助记录类型与一个多态字段,非常类似于上述结构体。

+0

谢谢!什么是最体面的解决方法?我不熟悉“eta扩展”并专门研究splitter(我现在使用的解决方法)不是一个可行的解决方案 – RUser4512

+0

确实没有直接的解决方法,但请参阅我的编辑。 –