Extending an existing type in OCaml

半城伤御伤魂 提交于 2019-11-28 09:45:08
Rémi

An interesting solution is to use polymorphic variant:

type bexp =
[ `And of bexp * bexp
| `Or of bexp * bexp
| `Xor of bexp * bexp
| `Not of bexp ];;

type nbexp = [ bexp | `Nop of nbexp ];;

Note that polymorphic variants are trickier than normal ones, but allow extension of type.

An interesting example of expression evaluation, with extension, using polymorphic variant can be found in a test directories of the ocaml source, see the svn

As you yourself correctly surmise, this is not possible in algebraic types. I agree with Apocalisp's suggestion that you may simply wrap the "inherited" part of nbexp in a constructor of its own.

I would add that the lack of inheritance of algebraic types is part of their wonderfulness. This means that an expression such as And(foo, bar) is umambiguously typed, and that casting (either up or down) has no role to play in the type system. This yields both greater safety and greater clarity. It does of course require of the programmer that s/he explicitly handle the cases where s/he wants to interact with the bexp parts of nbexp, but if you think about it, that's how the increased safety and clarity is realised in practice.

Hey, these are supposed to be Algebraic data types, right?

Right. And algebraic data types are constructed by tagged (aka discriminated) unions and products. What you want is just a (non-tagged) union, which is not an algebraic data type and isn't supported by Haskell. OCaml has polymorphic variants (see other answers).

Typed Scheme does support non-tagged unions, so you may want to check it out.

Update: Ocaml now has extensible types. http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec246

Here you would do

type bexpr += Nop of bexpr
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!