fixity declaration has form infix(l|r)? [Digit] in haskell. I'm pretty sure, that this is not enough for complicated cases. Ideally, fixity declarations should have form infix(l|r)? [Digit](\.(+|-)[Digit])* , with implied infinitely long repeated (.0) tail. This will allow fine tuning of operator priorities and much easier priority selection. For example, it may be assumed, that bit operations like (.&.) operator have hightest priority and have priorities like 9.0.1 or 9.0.2, anti-lisps like ($) have lowest priority like 0.0.1, control operators have base priority 1.* and logic operations like (&&) have priority of 2.* and it will be possibly to add new operators between or above all (for example) control operators without moving fixity of other ones.
Agda2 language supports wide priority range, but still without 'tails' to my knowledge. Is there any haskell-influenced language or experimental syntactic extension that address the issue?
_______________________________________________
Haskell-Cafe mailing list
Haskel...@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
> When I was implementing a toy functional languages compiler I did away with
precedence declarations by number and instead allowed the programmer to
specify a partial order on declarations; this seems to be a much cleaner
solution and avoids arbitrary precedences between otherwise unrelated
operators defined in different modules.
I agree. I don't declare operators very often, and when I do I always struggle
to remember which way round the precedence numbers go. I usually end up
hunting for a Prelude operator that works the way I'm aiming for, then copy
its definition. It would be much easier to declare the fixity of myop to be
same as someotherop (which would presumably have to be already declared/fixed
in an imported module).
[It's also slightly counterintuitive that the thing being defined comes last
in an infix declaration, and that the stand-alone operator isn't in parens.]
infixAs !! .$ -- fixing myop (.$) to be fixed as Preludeop (!!)
If you wanted to define precedence relative to some other operator(s), it
might be clearer to give some model parsings (grabbing some syntax something
like Ryan's):
infix .$ (x ** y .$ z .$ w) ==> (x ** ((y .$ z) .$ w))
-- === infixl 9 .$
OTOH, I think Евгений's proposal is getting too exotic. Do we really need such
fine shades of binding? Will the reader remember how each operator binds
relative to the others? Surely a case where explicit parens would be better.
(Anything else we can bikeshed about while we're at it?)
AntC
Your idea looks _much_ better from code clarity point of view, but it's unclear to me, how to deal with it internally and in error messages. I'm not a compiler guy, though.
Worse, it does not allow to set up fixity relative to operator that is not in scope and it will create unnecessary intermodule dependencies. One should fall back to numeric fixities for such cases, if it is needed.
On Tue, Aug 14, 2012 at 1:04 AM, Евгений Пермяков <perm...@gmail.com> wrote:
Your idea looks _much_ better from code clarity point of view, but it's unclear to me, how to deal with it internally and in error messages. I'm not a compiler guy, though.
How to deal with it internally: It's pretty easy, actually. The hardest part is implementing an extensible partial order; once you have that and you can use it to drive comparisons, parsing is not hard.
Basically, at each step when you read an operator token, you need to decide to "shift", that is, put it onto a stack of operations, "reduce", that is, apply the operator at the top of the stack (leaving the current token to check again at the next step), or give a parse error. The rules for deciding which of those to do are pretty simple:
I would expect modules to declare locally relative fixities between operators imported from different modules if and only if it was relevant to that module's implementation.
In most cases I expect the non-ordering to be resolved by adding parentheses, not by declaring additional precedence directives; for example, even though (a == b == c) would be a parse error due to == being non-associative, both ((a == b) == c) and (a == (b == c)) are not. The same method of 'just add parentheses where you mean it' fixes any parse error due to incomparable precedences.
-- ryan