Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#3155 closed bug (fixed)

TypeOperators/Rank2Types clash

Reported by: MartijnVanSteenbergen Owned by:
Priority: normal Milestone:
Component: Compiler Version: 6.10.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: typecheck/should_fail/T3155
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Consider the following piece of code:


data Any s where
  Any :: s ix -> ix -> Any s

data AnyR s r where
  AnyR :: s ix -> r ix -> AnyR s r

unR :: (forall ix. r ix -> ix) -> AnyR s r -> Any s
unR f (AnyR ix rix) = Any ix (f rix)

GHC reports:

    Illegal operator `.' in type `forall ix . (r ix -> ix)'
      Perhaps you intended to use -XRankNTypes or similar flag
      to enable explicit-forall syntax: forall <tvs>. <type>

Enabling TypeOperators causes the error to change to:

    Occurs check: cannot construct the infinite type: ix = r ix
    In the pattern: AnyR ix rix
    In the definition of `unR': unR f (AnyR ix rix) = Any ix (f rix)

Which is very confusing, as the solution (still) is to turn on Rank2Types.

Could it be made so that the error message stays the same when TypeOperators is turned on?

Change History (4)

comment:1 Changed 10 years ago by simonpj

difficulty: Unknown

It's not clear what is the right thing to do. In principle, if you have type operators, but not rank-n types, then the type you wrote could mean

unR :: forall f d ix r s.  (d (f ix)(r ix) -> ix) -> AnyR s r -> Any s

where I have used f instead of forall, and d instead of (.). I made these substitutions because with TypeOperators but without RankNTypes that's what GHC sees.

That's a legitimate type signature, and it gives rise to the message you saw.

I suppose we could permanently remove (.) from what a "type operator" can be, since anyone using type operators will also be familiar with rank-n types, so re-using (.) as an operator seems confusing. That might help.

Does anyone have other ideas?


comment:2 Changed 10 years ago by MartijnVanSteenbergen says:

A type variable can be an (unqualified) operator e.g. +. The lexical syntax is the same as that for variable operators, excluding "(.)", "(!)", and "(*)".

Does that last sentence mean that . already is an illegal type operator?

The reason I find the example above particularly confusing is that to me "infinite type" is one of the more frustrating error messages, because the error is always about a declaration as a whole; I never know where to start looking for a fix. I spent a while looking for missing/surplus arguments before I realised that Rank2Types hadn't been enabled yet. :-)

comment:3 Changed 10 years ago by simonpj

Resolution: fixed
Status: newclosed
Test Case: typecheck/should_fail/T3155

Ah yes, good point. I've jiggled a bit more. Now you get the good error message either way. Thanks.

Thu Apr  9 15:40:04 BST 2009
  * Fix Trac #3155: better error message when -XRankNTypes is omitted
  This patch sligtly re-adjusts the way in which the syntax of types 
  is handled:
   * In the lexer, '.' and '*' are always accepted in types
     (previously it was conditional).  This things can't mean
     anything else in H98, which is the only reason for doing things
     conditionally in the lexer.
   * As a result '.' in types is never treated as an operator.
     Instead, lacking a 'forall' keyword, it turns into a plain parse error.
   * Test for -XKindSignatures in the renamer when processing
       a) type variable bindings
       b) types with sigs (ty :: kind-sig)
   * Make -XKindSignatures be implied by -XTypeFamilies 
     Previously this was buried in the conditonal lexing of '*'

    M ./compiler/main/DynFlags.hs +2
    M ./compiler/parser/Lexer.x -2 +2
    M ./compiler/parser/Parser.y.pp +5
    M ./compiler/parser/RdrHsSyn.lhs -1 +2
    M ./compiler/rename/RnEnv.lhs -8 +16
    M ./compiler/rename/RnTypes.lhs -3 +5


comment:4 Changed 10 years ago by MartijnVanSteenbergen

Thanks. :-) I'm always amazed at how fast you (plural) fix the bugs I report.

Note: See TracTickets for help on using tickets.