2
Some thoughts on fixities
3
-------------------------
5
** The target of a fixity declaration
7
When you declare a fixity it should refer to a particular binding of that
8
name, not (as in Haskell) the name in general. The reason for this is: it's a
9
good design. A particular name might mean different things at different times,
10
and so you should be able to assign it different fixities.
12
One option then is to somehow attach the fixity declaration to the binding
13
site of the name. An argument against this is that it's very nice to give all
14
the fixity information in one place:
19
Instead of attaching it to the different definitions.
21
** The scope of a fixity declaration
23
So the question is then what declaration are we referring to when we say
27
A simple answer is: the <> in scope. Consider then the following example:
29
suc x + y = suc (x + y)
32
What's the fixity of + in the body? It clearly has to be infixl 10, since how
33
else would you declare it? This illustrates that fixity declarations follow
34
different scoping rules from normal declarations.
36
If we accept that the scoping for fixity declarations is weird, would there be
37
any problems in allowing the fixity to appear before the definition of the
41
suc x + y = suc (x + y)
43
Not really. We just get weird scoping in a different way.
45
** Local fixity declarations
47
The examples, so far has been about fixities of declared names. You could also
48
imaging declaring fixities for bound names:
50
\(+) -> let infixl 9 + in 1 + 2 + 3
52
We'll get back to that shortly.
54
Another thing to consider is whether it should be possible to redefine the
55
fixity of a function. Let's look at the consequences:
59
We should be able to write something like the following
67
So far nothing strange. What about this example:
77
Following what we've said the fixity of + in x should be infixl 10, but this
78
looks really weird, considering that we declare the fixity of + in the line
79
above x to be infixr 8. In fact it's not even clear which definition of +
80
this fixity declaration refers to.
84
Considering the example above this seems like the best choice. There is a
85
problem with declaring the fixity of bound names, though. For declared names
86
the restriction is simply that the fixity declaration must appear at the
87
same level (same module/abstract/private/mutual/let-block), for bound names
88
it's not that simple. For instance, we would expect the example above to be
91
\(+) -> let infixl 9 + in 1 + 2 + 3
93
But then we get into the same problem as if we allow redefinition of
96
\(+) -> let infixl 9 +
102
Which + are we declaring the fixity of? To solve this problem we don't allow
103
fixity declarations for bound names.
107
Actually the restriction on where the fixity declaration can appear isn't that
108
simple as let on above. As mentioned in the beginning it's nice to group the
109
fixity declarations of related functions. If some of these functions are
110
abstract, private or mutually recursive you wouldn't be able to do this. The
111
solution is to use the scoping rule for the blocks. If a name declared inside
112
a block is visible outside the block, then the fixity declaration can appear
113
outside the block. This means that you can pull fixity declarations out of
114
abstract, private, and mutual blocks, but not out of modules of local
117
A natural question is if we are allowed to push fixities inside these blocks:
122
There's not really a problem with doing this except that since the declaration
123
modifiers (private/abstract/mutual) doesn't affect fixity declarations the
124
example above could give you the wrong idea (that the fixity isn't exported
125
outside the module). For this reason, the example above is disallowed.
129
You can declare the fixity of a declared name (but not a bound name). The
130
fixity declaration has to appear on the same level as the declaration. The
131
only exception to this rule is that fixity declarations can be lifted out of
132
abstract, private and mutual blocks.
134
The following would be OK:
149
but the following would not be
151
abstract infixl 8 +, -
159
vim: sts=2 sw=2 tw=80