Opened 2 years ago

Last modified 4 months ago

#10141 new bug

CUSK mysteries

Reported by: goldfire Owned by: goldfire
Priority: normal Milestone: 8.4.1
Component: Compiler Version: 7.10.1-rc2
Keywords: TypeFamilies, TypeInType Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: indexed-types/should_fail/T10141
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Take the following definition:

type family G (a :: k) where
   G Int  = Bool
   G Bool = Int
   G a    = a

It compiles in 7.8.3, but not in 7.10.1 RC2. This makes me sad. I will fix.

(Found by Jan Stolarek.)

Change History (18)

comment:1 Changed 2 years ago by simonpj

This looks bad. Release blocker? I assume so. Say if not.

comment:2 Changed 2 years ago by goldfire

Resolution: invalid
Status: newclosed

This is by design. As I discovered en route to the solution to #9200, the old kind inference for closed type families was bogus. For the type family above, what should the return kind be? k, k2, and * are all viable options. Thus, this type family has no principal kind and should be rejected.

Another was of looking at this is that G does not have a CUSK. Therefore, its right-hand side must use kind variables uniformly -- which it doesn't, because the first two equations must specialize k to *.

So, closing as invalid.

comment:3 Changed 2 years ago by rwbarton

In this particular case, given the third equation G a = a, I'm pretty sure the only possible return kind is k, no? But there was that whole long discussion about CUSKs that I didn't really follow, so I take it that in general a closed type family may have no principal kind.

I would venture to say though that the error message GHC produces is IMHO not that helpful. In this case the fix is clearly to add a CUSK type family G (a :: k) :: k where; could GHC work out when it is appropriate to suggest adding a CUSK?

comment:4 in reply to:  2 Changed 2 years ago by jstolarek

Owner: goldfire deleted
Resolution: invalid
Status: closednew

Replying to goldfire:

So, closing as invalid.

I believe we should create a test case so that any accidental change of semantics does not go unnoticed (like it seems to have between 7.8.3 and 7.10.1?). Richard, I'm re-opening and assigning to you but if you don't have the time please re-assign it to me - I'll take care of that in due time.

comment:5 Changed 2 years ago by jstolarek

Owner: set to goldfire

comment:6 Changed 2 years ago by goldfire

Responding to comment:3:

No, the return kind could well be *. I'll rewrite with explicit kinds:

type family G (a :: k) :: * where
  G * Int  = Bool
  G * Bool = Int
  G * a    = a

This G doesn't really use its kind-polymorphism, but the definition kind checks.

However, I think you're right about the suggestion for a CUSK, here and in other cases. And I think it's possible for GHC to have at least some heuristics for when a CUSK is the answer. Specifically, it could include a note about CUSKs in error messages that arise from kind mismatches in non-CUSK right-hand sides.

And, yes, this would make for a decent test case. Thanks for the suggestion.

I'm very unsure I can get to this by Friday (the next RC release), though!

comment:7 Changed 2 years ago by goldfire

Priority: highestnormal

comment:8 Changed 2 years ago by thoughtpolice


Moving to 7.12.1 milestone.

comment:9 Changed 2 years ago by goldfire

I've added a (not-yet-pushed) test case, but it's hard to see how to improve error messages. The problem is that the place that generates the kind errors is far from where we know whether or not we have a CUSK. I attempted to use addErrCtxt to include a note about CUSKs before kind-checking, but this note got appended to lots of errors that are clearly unrelated to CUSKs -- this is the wrong approach. I think the right approach is to somehow record in TcM that we're kind-checking a declaration which could potentially have a CUSK but in fact does not and then look there before reporting certain errors. But this is terribly heavy.

Perhaps after my branch is merged, a way forward will present itself.

comment:10 Changed 2 years ago by Richard Eisenberg <eir@…>

comment:11 Changed 2 years ago by simonpj

Test Case: indexed-types/should_fail/T10141

comment:12 Changed 23 months ago by thoughtpolice


Milestone renamed

comment:13 Changed 18 months ago by thomie

Keywords: TypeFamilies added

comment:14 Changed 17 months ago by bgamari


This bug won't be fixed in 8.0.1; bumping to 8.2.

comment:15 Changed 6 months ago by simonpj

Summary: Kind inference regression in closed type familiesCUSK mysteries

Here's an example that I was baffled by. This works

type family F (a :: k)
type instance F Maybe = Char

But this does not.

type family F (a :: k) where -- = r  | r -> a where
  F Maybe = Char

The latter is rejected with

Foo.hs:6:5: error:
    * Expecting one more argument to `Maybe'
      Expected kind `k', but `Maybe' has kind `* -> *'
    * In the first argument of `F', namely `Maybe'
      In the type family declaration for `F'

It is bizarre that one works and the other does not, and I was all ready to open a ticket when Richard said: This is correct behavior. The former has a CUSK, as all open type families have CUSKs with un-annotated kinds defaulting to Type. The latter does not have a CUSK, because the result kind is unknown. You therefore cannot specialize the k variable in the definition of the latter.

I can't help feeling that our CUSK story is a bit wonky, so I'm recording it here.

comment:16 Changed 6 months ago by simonpj

Keywords: TypeInType added

comment:17 Changed 6 months ago by goldfire

If you want TypeInType to mean "Richard's bailiwick", that's perhaps convenient. But I'll note that this problem has nothing to do with -XTypeInType and exists in 7.10 and perhaps 7.8.

comment:18 Changed 4 months ago by bgamari


Given that 8.2.1-rc1 is imminent, I'm bumping these off to the 8.4

Note: See TracTickets for help on using tickets.