[GHC] #10056: Inconsistent precedence of ~
GHC
ghc-devs at haskell.org
Mon Feb 2 01:54:29 UTC 2015
#10056: Inconsistent precedence of ~
-------------------------------------+-------------------------------------
Reporter: crockeea | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.4
(Parser) | Keywords:
Resolution: | Architecture:
Operating System: Unknown/Multiple | Unknown/Multiple
Type of failure: GHC rejects | Test Case:
valid program | Blocking:
Blocked By: | Differential Revisions:
Related Tickets: |
-------------------------------------+-------------------------------------
Comment (by goldfire):
Here's what I know about all of this, to the best of my knowledge:
- Types do ''not'' "inherit" fixity from terms. The type family `(+) :: *
-> * -> *` (or whatever kinds) is completely and totally unrelated to the
term-level variable `(+) :: Num a => a -> a -> a`.
- There is no way in a fixity declaration to specify what namespace you
want the declaration to operate over. So, in (what I consider to be) a
terrible hack, a fixity declaration will affect either or both of local
term-level and type-level definitions. So, if you have
{{{
(//) :: a -> a -> a
(//) = ...
type family (//) a b
infixl 5 //
}}}
then ''both'' the term `(//)` and the type `(//)` get the given fixity.
This isn't a case of one inheriting the fixity from the other or being at
all related -- it's just a peculiar meaning given to a fixity declaration.
- While the parser doesn't know what type a term has, it ''does'' know
whether you're writing a term, a type, or a kind. So it can behave
differently in each of these cases -- they're all syntactically distinct
in Haskell source.
- Traditional fixity declarations don't affect the parser. And, upon some
thought, we realize they can't: a fixity declaration can't be acted upon
until after (or in) the renamer, when we know where a symbol is declared.
- `(~)` is parsed separately from the normal infix operators. Recall that
`TypeOperators` used to require type-level operators to begin with `:`.
`(~)` does not, and so it must be special. Now that `TypeOperators` has
been changed, there actually doesn't seem to be a good reason to keep
`(~)` special. It's declared (in `ghc-prim:GHC.Types`). It has magic in
the solver, but there needs to be no magic dealing with naming or parsing.
However, simply removing the magic causes several minor conundrums:
- Do we require `TypeOperators` when `~` appears in source code?
Currently, we don't.
- Do we require `TypeFamilies` or `GADTs` when `~` appears in source
code? Currently, we do, but if we drop the magic, this decision is
suspect, especially if `~` isn't ever really acted on in the module
(because it appears only on the RHS of a type synonym, say).
- Should `(~)` be imported as part of the Prelude? If no, then a lot of
code breaks. If yes, that implies that hiding the Prelude also hides
`(~)`, breaking less code, but still breaking code.
These issues are surmountable, perhaps, but when I looked at making `~`
non-magical, I discovered both that it's technically quite straightforward
and socially rather annoying for little benefit. I suppose there's a
middle road where it's non-magical in the parser but magical in the
renamer.
When I realized how tangled this all was, I gave up, as I was just doing
some cleaning. Now that bugs are actually appearing, there might be more
incentive to come up with a consistent response.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10056#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list