Россия, Петерубрг, СПБ-ГПУ, 1998 |
Выражения
3.4 Применение операторов
exp | -> | exp1 qop exp2 | |
| | - exp | (префиксное отрицание) | |
qop | -> | qvarop | qconop | (квалифицированный оператор) |
Перевод:
выражение | -> | выражение1 квалифицированный-оператор выражение2 | |
| | - выражение | (префиксное отрицание) | |
квалифицированный-оператор | -> | квалифицированный-оператор-переменной | квалифицированный-оператор-конструктора | (квалифицированный оператор) |
Форма e1 qop e2 представляет собой инфиксное применение бинарного оператора qop к выражениям e1 и e2.
Специальная форма -e обозначает префиксное отрицание, единственный префиксный оператор в Haskell , и является синтаксической записью отрицания (e). Бинарный оператор - необязательно ссылается на определение - в Prelude, он может быть переопределен системой модуля. Тем не менее, унарный оператор - будет всегда ссылаться на функцию negate, определенную в Prelude. Нет никакой связи между локальным значением оператора - и унарным отрицанием.
Префиксный оператор отрицания имеет тот же приоритет, что и инфиксный оператор -, определенный в Prelude (см. таблицу в п.4.4.3). Поскольку e1-e2 при разборе интерпретируется как инфиксное применение бинарного оператора -, для альтернативной интерпретации нужно писать e1(-e2). Аналогично, (-) является синтаксической записью (\ x y -> x-y), как и любой инфиксный оператор, и не обозначает (\ x -> -x) - для этого нужно использовать negate.
3.5 Сечения
aexp | -> | ( expi+1 qop(a,i) ) | (левое сечение) |
| | ( lexpi qop(l,i) ) | (левое сечение) | |
| | ( qop(a,i)<> expi+1 ) | (правое сечение) | |
| | ( qop(r,i)< -> < -> rexpi ) | (правое сечение) |
Перевод:
выражение-аргумента | -> | ( выражениеi+1 квалифицированный-оператор(a,i) ) | (левое сечение) |
| | ( левое-сечение-выраженияi квалифицированный-оператор(l,i) ) | (левое сечение) | |
| | ( квалифицированный-оператор(a,i)<-> выражениеi+1 ) | (правое сечение) | |
| | ( квалифицированный-оператор(r,i)<-> правое-сечение-выраженияi ) | (правое сечение) |
Сечения записываются в виде ( op e ) или ( e op ), где op - бинарный оператор, а e - выражение. Сечения представляют собой удобный синтаксис для записи частичного применения бинарных операторов.
Синтаксические правила приоритетов применяются к сечениям следующим образом. (op e) допустимо, если и только если (x op e) при разборе интерпретируется так же, как и (x op (e)) ; аналогично для (e op). Например, (*a+b) синтаксически недопустимо, но (+a*b) и (*(a+b)) допустимы. Поскольку оператор (+) левоассоциативен, (a+b+) синтаксически правильно, а (+a+b) - нет, его можно правильно записать в виде (+(a+b)). В качестве другого примера рассмотрим выражение
(let n = 10 in n +)
которое является недопустимым в соответствии с мета-правилом для let/лямбда (раздел "3" ). Выражение
(let n = 10 in n + x)
при разборе интерпретируется как
(let n = 10 in (n + x))
вместо
((let n = 10 in n) + x)
Поскольку - интерпретируется в грамматике специальным образом, (- exp) является не сечением, а применением префиксного оператора отрицания, в соответствии с описанием в предыдущем разделе. Тем не менее, имеется функция subtract, определенная в Prelude таким образом, что (subtract exp) эквивалентно недопустимому ранее сечению. Для той же цели может служить выражение (+ (- exp)).
Трансляция:
Выполняются следующие тождества:
где op - бинарный оператор, e - выражение, а x - переменная, которая не является свободной в e.
3.6 Условные выражения
Перевод:
Условное выражение имеет вид if e1 then e2 else e3 и возвращает: значение e2 - если значение e1 равно True, e3 - если e1 равно False, и _|_ - иначе.
Трансляция:
Выполняются следующие тождества:
if e1 then e2 else e3= case e1 of { True -> e2 ; False -> e3 }
где True и False - конструкторы с нулевым числом аргументов из типа Bool, определенные в Prelude. Тип e1 должен быть Bool, e2 и e3 должны иметь тот же тип, который также является типом всего условного выражения.