Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

:. and :! aren't assigned fixity declarations #322

Closed
RyanGlScott opened this issue Apr 20, 2018 · 2 comments
Closed

:. and :! aren't assigned fixity declarations #322

RyanGlScott opened this issue Apr 20, 2018 · 2 comments
Labels

Comments

@RyanGlScott
Copy link
Collaborator

To see what I mean, observe that the following program fails to typecheck:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Bug where

import Data.Singletons.Prelude
import Data.Singletons.TH

$(singletons [d|
  (!) :: Bool -> Bool -> Bool
  (!) = (||)
  infixr 2 !
  |])

f1 :: (False && True :! True) :~: True
f1 = Refl
$ ghc Bug.hs
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o )

Bug.hs:20:6: error:
    • Couldn't match type ‘'True’ with ‘'False’
      Expected type: ('False && ('True :! 'True)) :~: 'True
        Actual type: 'True :~: 'True
    • In the expression: Refl
      In an equation for ‘f1’: f1 = Refl
   |
20 | f1 = Refl
   |      ^^^^

It ought to, though, since we declared the the fixity of (!) (and thus (:!)) to be infixr 2, so False && True :! True should associate as (False && True) :! True. However, it appears that in practice, (:!) isn't given a fixity declaration, so that expression actually associates as False && (True :! True).

Indeed, searching through the -ddump-splices output reveals no fixity declaration for (:!). (There is one for (%!), however.)

The same problem also affects (.), which promotes to (:.).

@RyanGlScott
Copy link
Collaborator Author

RyanGlScott commented Apr 20, 2018

Ugh, it turns out that I'm the one who caused these shenanigans. The culprit is here:

promoteInfixDecl :: Fixity -> Name -> Maybe DDec
promoteInfixDecl fixity name
| isDataConName name || not (isHsLetter (head (nameBase name)))
= Nothing -- No need to promote fixity declarations for constructor names or
-- infix names, as those fixity declarations apply to both
-- the value and type namespaces.

Here, I boldly claim that no non-alphanumeric identifiers need to have their fixity declarations promoted, since their promoted names as the same as their unpromoted ones. However, there are exactly two exceptions to this rule: (.) and (!), as it turns out.

Fix incoming.

@RyanGlScott
Copy link
Collaborator Author

Fixed in f13482a.

Note that I didn't add a test case for (.) since it proves to be trickier than you'd expect. See #323.

RyanGlScott added a commit that referenced this issue Apr 20, 2018
Instead of manually hard-coding the special cases, we can simply
check if a name is equal to its promoted counterpart, which is much
more robust.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant