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

Types Ocaml-具有多态参数的构造函数,types,polymorphism,ocaml,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
类型,每个算术和布尔运算符都有一个构造函数。我想将这种类型分解为以下几类:

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”多态性

我做错什么了吗?有没有合适的方法来实现这种多态性


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

我不能排除这是的一个实例,但如果您真的需要,可以在OCaml 4.03中直接将记录类型(可以具有完全多态字段)声明为类型构造函数的参数,如:

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

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

我不能排除这是的一个实例,但如果您真的需要,可以使用OCaml 4.03直接将记录类型(可以具有完全多态字段)声明为类型构造函数的参数,如:

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

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

这并不能完全回答你的问题,但你可能想让你的AST更具象征性。例如:

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

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

然后,当您计算表达式时,可以调用
(=)
()这并不完全回答您的问题,但您可能希望使AST更具符号性。例如:

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

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

然后,当您计算表达式时,您可以调用
(=)
(感谢您提到记录。至于XY问题:对我来说,为每个运算符都设置构造函数似乎是一个糟糕的设计(特别是因为它们是函数)。我真的只是想改进我的实现,我希望我的问题反映了这一点。感谢提及记录。至于XY问题:每个操作符都有一个构造函数对我来说是一个糟糕的设计(特别是因为它们是函数)。我真的只是想改进我的实现,我希望我的问题反映了这一点。你可能想学习GADT来实现类似的功能。请注意,由于函数是不透明的值,你将无法在
expr
s上实现任何有用的操作。它们甚至无法在顶层打印ch是一条路。@RichouHunter:谢谢你的建议!这个概念对我的学习水平来说仍然很先进,但感觉非常合适。我一定会仔细研究它。@gsg:是的,我后来意识到我无法模式匹配函数,并期望它像C中的函数指针比较一样工作。考虑到我现在的实现,埃蒂安的技术肯定更好。@lephe:现在开始学习GADT还为时过早,GADT确实是一个广泛的话题。你可能想学习GADT来实现类似的目标。请注意,由于函数是不透明的值,你将无法在
expr
s上实现任何有用的操作。它们将甚至不能在顶层打印有用的内容。埃蒂安的方法是可行的。@RichouHunter:谢谢你的建议!这个概念对我的学习水平来说仍然很先进,但感觉非常合适。我肯定会仔细研究它。@gsg:是的,我后来意识到我无法匹配函数的模式,并期望它能工作。@gsg:是的,我后来意识到我无法匹配函数并期望它能工作在C语言中比较函数指针。考虑到我现在的实现状态,埃蒂安的技术肯定更好。@lephe:开始学习GADT永远不会太早,它确实是一个广泛的话题。