Opened 4 months ago

Last modified 3 months ago

#15235 patch bug

GHCi's claim of infixr 0 (->) is a lie

Reported by: RyanGlScott Owned by:
Priority: normal Milestone: 8.8.1
Component: Compiler Version: 8.4.3
Keywords: newcomer Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: #15236 Differential Rev(s):
Wiki Page:

Description

Currently, if you query the :info for (->) in GHCi, it will give you:

$ ghci
GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/ryanglscott/.ghci
λ> :i (->)
data (->) (a :: TYPE q) (b :: TYPE r)   -- Defined in ‘GHC.Prim’
infixr 0 `(->)`
<instances elided>

This fixity information appears to be plain wrong, as the following program demonstrates:

{-# LANGUAGE TypeOperators #-}
module Bug where

import Data.Type.Equality

type (~>) = (->)
infixr 0 ~>

f :: (a ~> b -> c) :~: (a ~> (b -> c))
f = Refl

Since (~>) and (->) are both infixr 0, I would expect a ~> b -> c to associate as a ~> (b -> c), like the type signature for f wants to prove. However, GHC believes otherwise:

$ ghc Bug.hs                                                                                      
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o )                                              
                                                                                                   
Bug.hs:10:5: error:                                                                                
    • Occurs check: cannot construct the infinite type: a ~ a ~> b                                 
      Expected type: ((a ~> b) -> c) :~: (a ~> (b -> c))
        Actual type: ((a ~> b) -> c) :~: ((a ~> b) -> c)
    • In the expression: Refl
      In an equation for ‘f’: f = Refl
    • Relevant bindings include
        f :: ((a ~> b) -> c) :~: (a ~> (b -> c)) (bound at Bug.hs:10:1)
   |
10 | f = Refl
   |     ^^^^

Reading the error message above, it appears that GHC gives (->) an even lower precedence than 0, since it associates a ~> b -> c as (a ~> b) -> c.

I'm not sure how to reconcile these two facts. There are at least a couple of options I can think of:

  1. Claim (->) has a negative fixity.
  2. Try to change GHC so that (->) really is infixr 0.

Change History (7)

comment:1 Changed 3 months ago by goldfire

I've been bitten by this before.

I'm worried about breakage with option (2), so I favor option (1), even if negative fixities are not available to users.

While we're in town, it should be infixr (-1) ->, without parentheses/backticks around the arrow.

comment:2 in reply to:  1 Changed 3 months ago by RyanGlScott

Replying to goldfire:

I'm worried about breakage with option (2), so I favor option (1), even if negative fixities are not available to users.

Sounds good to me.

While we're in town, it should be infixr (-1) ->, without parentheses/backticks around the arrow.

This was done separately in #15236.

comment:3 Changed 3 months ago by bgamari

Milestone: 8.6.18.8.1

These won't be addressed in GHC 8.6.

comment:4 Changed 3 months ago by RyanGlScott

Changing GHCi's fixity information for (->) is a simple matter of applying this change:

  • compiler/basicTypes/BasicTypes.hs

    diff --git a/compiler/basicTypes/BasicTypes.hs b/compiler/basicTypes/BasicTypes.hs
    index 93010b7..e9d32f6 100644
    a b defaultFixity = Fixity NoSourceText maxPrecedence InfixL 
    409409negateFixity, funTyFixity :: Fixity
    410410-- Wired-in fixities
    411411negateFixity = Fixity NoSourceText 6 InfixL  -- Fixity of unary negate
    412 funTyFixity  = Fixity NoSourceText 0 InfixR  -- Fixity of '->'
     412funTyFixity  = Fixity NoSourceText (-1) InfixR  -- Fixity of '->'
    413413
    414414{-
    415415Consider

However, there's one more question we should answer before applying this change: do we want the displayed :info output to be this:

infixr -1 ->

Or this?

infixr (-1) ->

With only the above change, :info will display the former. If we want the latter, we'd have to make additional changes to the pretty-printer output for fixity information to add parentheses.

comment:5 Changed 3 months ago by simonpj

I don't think it matters much, so I'd be inclined to do whatever is least work.

comment:6 Changed 3 months ago by RyanGlScott

Keywords: newcomer added

Sounds good to me. This would be a good task for someone wanting to get involved with GHC development, so I'll mark this as a newcomer ticket. All you'd need to do is apply the change in comment:4, and include a comment explaining why this negative fixity is used.

comment:7 Changed 3 months ago by RyanGlScott

Status: newpatch
Note: See TracTickets for help on using tickets.