This note contains some thoughts about infix and bracketing operators like the following examples:
a <| b |> c a --[ b1, .. , bk ]--> c [], [ b1, .. , bk ] ...The first (ternary) operator was introduced by Hoare [`A couple of novelties in the propositional calculus' Zeitschr, f. math. Logik under Grundlagen d. Math 1985]] to represent conditional expressions. (In the forword to Hoare's CSP book, Dijkstra refers to Hoare as "notationally intrepid". I believe that the symbols
<|
and
|>
are sometimes known as "Toblerone brackets".) The
middle operand is the boolean condition, the first one is the `then',
and the last one is the `else'. Hoare's notation has among its merits
that it makes it easier to spot opportunities for using algebraic laws
of idempotence, associativity, symmetry, distributivity and so on.
The second notation is a generalisation of such Hoare-style split
operators. The operator is in two `halves' --[
and ]-->
. The two
halves of the operator should be thought of as delimiting the scope of
a nested grammar in which comma is a (say) right associative infix
operator, of lowest precedence.
The third line shows Haskell's built in notation for lists. Here the left and right operands have disappeared, and we are left only with the material in the middle.
This is probably all about "punctuation" in some broad sense.
grammar ::= (operator declaration)* operator declaration ::= "unary" ; symbol | "infix" ; symbol ; admin | "split" ; symbol ; grammar ; symbol ; admin admin ::= associativity ; precedence | precedence ; associativity associativity ::= "right associative" | "left associative" | "not associative" | nil precedence ::= "precedence" ; digit | nilPerhaps later grammar declarations should simply overide previous ones.
(op) (op e) = \ x -> x op e (e op) = \ x -> e op xIt can be very concise, and can help make important algebraic properties visible. Its abuse can also lead to hideous obfuscation.
How should section notation work for split operators? My inclination is to say it is fine, provided that the `middle' operands are all supplied. So one can use a section notation such as
(<| cond |>) (<| cond |> default) (patch <| cond |>)in connection with Hoare's operator (this appears to have been his intention).
What is the most general description of section notation?
split " " split * infix | right 0 *Could one arrange for things as complicated as C's string and character syntax? This probably needs a very strong notion of `symbol'.
We might want to escape some external operators, perhaps by prefixing them with for example a common symbol.
Haskell has only one, very special, prefix operator : `-' for minus.
Prefix. Where a leaf symbol `f' occur always at the head of a path of some specified length arity(f), we do not need brackets to represent binary trees - as in Polish notation. (This might become relevant as the global supply of parentheses dwindles.)
Postfix. Among postfix operators we have superscripts and subscripts, in which lowering and raising indicates a kind of bracketing. Apart from these `2-dimensional' things, it is striking how few postfix operators occur in nature. (Or is it? We have right sections. But they involve parentheses. Postfix notation for substitutions. `Algebraic' notation for application of functions.)
Indentation is a way of economising on parentheses (the dreadful expense of ink ...) by exploiting a two dimensional medium.
Juxtaposition is a very strange operator. It seems to play the role of a meta-operator - putting things `together' in a particular order. It needs no ink. It is the mother of all operators.
We use names in so many ways - as place holders, as constants, as links, as tags, as unknowns, .. .
Abadi and Cardelli have defined somewhere a lexically scoped extensible syntax that in some sense `copes with' not only names for bound variables but also names for selectors. (Maybe other uses of names too.)
Raanta (Type theoretical grammar).
Landin. sugar.