Ocaml - 具有多态参数的构造函数

时间:2018-03-06 07:22:28

标签: types polymorphism ocaml

在玩具功能语言的翻译中,我有一个expr类型,每个算术和布尔运算符都有一个构造函数。我想把这种类型分解成类似的东西:

type expr =
    | Int of int
    | BinaryArith of (int -> int -> int) * expr * expr
    | Comparison of ('a -> 'a -> bool)   * expr * expr

但是,由于'a类型参数未定义,因此不会输入。我可以完全参数化为'a expr,但expr的单个实例将不再提供多态行为。

最终,我希望将内置的比较运算符(<>>=等)传递给构造函数,所以我想在这里保留完整的多态性。

如果构造函数可以被视为函数,那么使得不可能的一个简单原因是Hindley-Milner类型系统仅支持“prenex”多态性。

我在这里做错了吗?有没有一种实现这种多态性的正确方法?

编辑:虽然接受者答案解决了这个问题,但在其他答案和评论中提出了更好的设计。一定要阅读它们!

2 个答案:

答案 0 :(得分:5)

它并没有完全回答你的问题,但你可能想让你的AST更具象征意义。例如:

type comparison_op = Eq | Ne | Lt | Gt | Le | Ge

type expr = ... | Comparison of comparison_op * expr * expr

然后,当您评估表达式时,可以拨打(=)(<=)等。

答案 1 :(得分:3)

我不能排除这是XY problem的一个实例,但是如果你真的需要它,那么从OCaml 4.03开始就有可能inline records,即声明记录type(可以具有完全多态字段)直接作为类型构造函数的参数,如:

type expr =
  | Int of int
  | BinaryArith of (int -> int -> int)
  | Comparison of { compare: 'a. 'a -> 'a -> bool }

let e = Comparison { compare = Pervasives.(=) }