Как Ocaml решает приоритет для пользовательских операторов?

Я хочу, чтобы хорошие операторы для сложной арифметики сделали мой код более удобочитаемым. Ocaml имеет комплексный модуль, поэтому я просто хочу добавить операторов, которые называют эти функции.

Самый интуитивный способ для меня - создать новый сложный оператор из всех обычных операторов, добавив '&' к символу оператора. Таким образом, + & и * & будет сложным сложение и умножение. Мне также хотелось бы ~ & быть сложным сопряжением.

Если я собираюсь использовать эти операторы, я хочу, чтобы они связывались так же, как и обычные арифметические отношения. Основываясь на следующих сеансах, они автоматически ведут себя так, как я хочу, но я хотел бы понять, почему, так что я не получаю ужасных ошибок при введении большего числа операторов.

Мое последнее предположение заключается в том, что их приоритет выполняется путем лексической сортировки символов оператора в соответствии с порядком, который согласуется с обычным арифметическим приоритетом. Но я не могу это подтвердить.

Первый сеанс:

# 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.}

Вторая сессия:

# 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.}

Ответ 1

В общем случае ассоциативность и приоритет оператора (если вы не выходите на camlp4 или что-то еще) основывается на первом символе оператора.

источник (ищите "приоритет ассоциативности для пользовательского оператора" ).

Невозможно определить его явно в OCaml (см. this, а также "Пользовательские операторы infix" на Сравнение Objective Caml и стандартного ML)

Вы можете использовать camlp4 или camlp5 для явного определения порядка функции infix. Кажется, что pa_do также может быть вариантом.

Я попытался написать пример, но я не знаком с camlp4, и это нелегко узнать за несколько минут.

Ответ 2

В руководстве OCaml, раздел 6.7, прокрутите вниз, прямо перед разделом 6.7.1. В таблице приоритета есть некоторые вещи, такие как +..., который включает любые пользовательские значения, начинающиеся с +. Неверно, что он всегда зависит от первого символа, поскольку **... имеет более высокий приоритет, чем *....

Ответ 3

Расширение синтаксиса pa-do для OCaml адресует именно эту проблему:

http://pa-do.forge.ocamlcore.org/

Вы можете использовать его для изменения приоритета оператора или, что более полезно в этом случае, использовать явный контекст для изменения значения операторов.