我最近一直在进行一些OCaml编程,以学习该语言并更熟悉函数式编程。最近,我开始认为我希望能够扩展现有类型(内置或我自己的类型),例如:
type bexp =
And of bexp * bexp
| Or of bexp * bexp
| Xor of bexp * bexp
| Not of bexp;;
现在让我们说我想向此类型添加Nop变体,但仅用于新类型-类似于继承。嘿,这些应该是代数数据类型,对吗?那么为什么不这样:
type nbexp = bexp | Nop nbexp ;;
...但这不是有效的OCaml,它给出了语法错误。基本上,我想做的是说我希望nbexp包含bexp包含的所有内容,并为此添加一个Nop。我想这是不可能的,因为,例如,如果您使用And构造函数,将无法确定它是bexp类型还是nbexp类型。 (我认为采用nbexp的构造函数Nop可能也会有问题。)
那么,有什么办法可以在OCaml中做类似的事情吗?而且,这是在Haskell中可行的事情吗(也许有类型类)?
最佳答案
一个有趣的解决方案是使用多态变体:
type bexp =
[ `And of bexp * bexp
| `Or of bexp * bexp
| `Xor of bexp * bexp
| `Not of bexp ];;
type nbexp = [ bexp | `Nop of nbexp ];;
请注意,多态变体比普通变体棘手,但允许类型扩展。
可以在ocaml源的测试目录中找到一个使用多态变体进行扩展的表达式评估的有趣示例,请参见svn。