Why is OCaml's (+) not polymorphic?

你离开我真会死。 提交于 2019-11-28 06:48:28

Ocaml does not support polymorphic operators (numeric or otherwise) other than comparison operators. The + versus +. thing removes a lot of subtle bugs which can crop up in converting different sizes of integers, floats, and other numeric types back and forth. It also means that the compiler always knows exactly which numeric type is in use, thus making it easier to recognize when the programmer has made incorrect assumptions about a number always having an integer value. Requiring explicit casting between numeric types may seem awkward, but in the long run, it probably saves you more time tracking down weird bugs than you have to spend to write that extra period to be explicit.

Aside from the . versions of the numeric operators, I do not think that the Ocaml syntax is particularly strange. It is very much in line with previous ML languages with appropriate and reasonable syntax extensions for its added features. If it initially seems odd to you, that probably simply indicates that you have been, thus far, only been programming in languages with closely related syntax. As you learn new languages, you will see that there are many different ways to have language syntax with different benefits and detriments, but a lot of it is just arbitrary conventions which someone decided on.

I would like the '+' operator to be polymorphic to support integer, float and so on. Why do we need '+.'?

Excellent question. There are many subtle trade-offs involved here.

The advantages of not overloading operators (as in OCaml) are:

  • Type inference is simpler and more predictable.
  • Code is more composable: moving code from one place to another cannot affect its meaning.
  • Predictable performance: you always know exactly which function is being invoked.

The disadvantages are:

  • Number of different operators quickly gets out of control: + for int, +. for float, +/ for arbitrary-precision rationals, +| for vectors, +|| for matrices and the complex numbers, low-dimensional vectors and matrices, homogeneous coordinates etc.

Some alternatives are:

Basically, the type systems of SML and OCaml (ignoring the object system and modules) do not support ad hoc polymorphism. This is a design decision. OCaml also, unlike SML, decided against including syntactic sugar for arithmetic.

Some languages in the ML family have extremely limited forms of ad hoc polymorphism in numeric operators. For instance, (+) in Standard ML has a default type of (int, int) -> int, but has type (float, float) -> float if its argument or return type is known to be float. These operators are special in SML, and could not be defined if they were not already built in. It also isn't possible to endow other values with this property. val add = (+) would have type (int, int) -> int. The specialness here is confined to the syntax of the language, there is no support for ad hoc polymorphism in the type system.

OCaml has a handful of operators with special semantics (but numeric operators are not among them), for instance || and && are short-circuit (but become long-circuit if you assign them to an intermediate value)

let long_circuit_or = (||);;
let print_true x = print_string x; true;;
(* just prints "4" *)
print_true "4" || print "5";;
(* prints "45" *)
long_circuit_or (print_true "4") (print_true "5");;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!