compiler-errors - OCaml 变量类型泛化

标签 compiler-errors compilation polymorphism ocaml

我正在尝试使用 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

我不明白为什么我可以声明一个专门的splitter12agenerate_splitter无法生成专门的拆分器。

最佳答案

你遇到了所谓的值(value)限制。有关解释,请参见例如this chapter中的同名部分真实世界的 Ocaml。

编辑:通常的解决方法(可能在该章中建议)是 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

另一种方法是使用带有多态字段的辅助记录类型,与上面的结构非常相似。

关于compiler-errors - OCaml 变量类型泛化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41789362/

相关文章:

c# - 错误 CS0117 : Namespace. A 不包含接口(interface)的定义

reactjs - react : Failed to compile; index. js

c# - 是否可以使用 .NET Core Roslyn 编译器编译单个 C# 代码文件?

c++ - 当我们编译 C++ 时,我们得到了什么?二进制代码 ?汇编代码?

c++ - 请告诉我为什么虚函数在以下代码中不起作用

java - 使用哪种模式来避免对象值转换器的代码重复

c# - 无法加载文件或程序集...参数不正确

c - 为什么我一直得到 "error: variable has incomplete type ' struct intVec'?

c - 使用 C99 编译时出现 'ISO C90' 错误,不允许 VLA

java - JAXB 编码和多态性