I want nice operators for complex arithmetic to make my code more readable. Ocaml has a Complex module, so I just want to add operators that call those functions.
The most intuitive way for me is to make a new complex operator from all of the usual operators by appending '&' to the operator symbol. Thus +& and *& will be complex addition and multiplication. I would also like ~& to be complex conjugation.
If I'm going to use these operators, I want them to associate the same way that normal arithmetic associates. Based on the following sessions, they are automatically behaving the way I want, but I would like to understand why, so that I don't get horrible bugs when I introduce more operators.
My current guess is that their precedence is done by lexically sorting the operator symbols according to an ordering that is consistent with normal arithmetic precedence. But I cannot confirm this.
Session one:
# open Complex;;
# let (+&) a b = add a b;;
val ( +& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# let ( *&) a b = mul a b;;
val ( *& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# one +& zero *& one +& zero *& one;;
- : Complex.t = {re = 1.; im = 0.}
# zero +& one *& zero +& one *& zero;;
- : Complex.t = {re = 0.; im = 0.}
# i +& i *& i +& i *& i *& i;;
- : Complex.t = {re = -1.; im = 0.}
Session two:
# open Complex;;
# let ( *&) a b = mul a b;;
val ( *& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# let (+&) a b = add a b;;
val ( +& ) : Complex.t -> Complex.t -> Complex.t = <fun>
# one +& zero *& one +& zero *& one;;
- : Complex.t = {re = 1.; im = 0.}
# zero +& one *& zero +& one *& zero;;
- : Complex.t = {re = 0.; im = 0.}
# i +& i *& i +& i *& i *& i;;
- : Complex.t = {re = -1.; im = 0.}
# let (~&) a = conj a;;
val ( ~& ) : Complex.t -> Complex.t = <fun>
# (one +& i) *& ~& (one +& i);;
- : Complex.t = {re = 2.; im = 0.}
It's right in the OCaml manual, section 6.7, scroll down, right before section 6.7.1. The precedence table has some things like +...
, which includes any user-defined starting with +
. It is not true that it always depends on the first character, as **...
has higher precedence than *...
.
In general, the associativity and precedence of an operator (unless you go out to camlp4 or something) is based on the operator's first character.
source (look for for "Associativity precedence for the user-defined operator").
There is no way to define it explicitly in OCaml (see this and also "User-defined infix operators" on Comparing Objective Caml and Standard ML)
You can use camlp4 or camlp5 to explicitly define the order of infix function. It seems like pa_do can also be an option.
I tried to write an example but I am not familiar with camlp4 and it is not easy to learn in a few minutes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With