Opened 7 months ago

Closed 7 months ago

Last modified 6 months ago

#15412 closed bug (fixed)

"Instance head is not headed by a class" when `Constraint` replaced with `type C = Constraint`

Reported by: Iceland_jack Owned by:
Priority: normal Milestone: 8.6.1
Component: Compiler Version: 8.4.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: testsuite/tests/typecheck/should_compile/T15412
Blocked By: Blocking:
Related Tickets: #15583 Differential Rev(s):
Wiki Page:

Description

{-# Language DataKinds, TypeInType, TypeFamilies #-}

import Data.Kind

newtype I a = I a

type C = Constraint

type family
  UnitC :: Constraint where
  UnitC = ()

instance UnitC => Functor I where
  fmap = undefined 

this works fine, but if I try to use the constraint synonym C (UnitC :: C where) fails with "Instance head is not headed by a class" which has no Google hits outside of the compiler

$ ghci -ignore-dot-ghci hs/249.hs
GHCi, version 8.5.20180128: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( hs/249.hs, interpreted )

hs/249.hs:13:10: error:
    • Instance head is not headed by a class
    • In the instance declaration for ‘Functor I’
   |
13 | instance UnitC => Functor I where
   |          ^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
Prelude> 

Change History (7)

comment:1 Changed 7 months ago by simonpj

Can you give the code that fails?

In general, in an instance

instance ... => C t1 t2 where ...

C must be a class; at least that's what the error message is complaining about.

comment:2 Changed 7 months ago by monoidal

The failing code is obtained by replacing Constraint by C in definition of UnitC:

{-# Language DataKinds, TypeInType, TypeFamilies #-}

import Data.Kind

newtype I a = I a

type C = Constraint

type family
  UnitC :: C where
  UnitC = ()

instance UnitC => Functor I where
  fmap = undefined
Last edited 7 months ago by monoidal (previous) (diff)

comment:3 Changed 7 months ago by Iceland_jack

Yes sorry, I should have included the failing code. Here is a version without type families

{-# Language DataKinds, TypeInType, ConstraintKinds #-}

import Data.Kind

data A :: Type

type C = Constraint
type UnitC = (() :: C)

instance UnitC => Eq A where
  (==) = undefined

comment:4 Changed 7 months ago by Simon Peyton Jones <simonpj@…>

In c5d31df7/ghc:

Treat isConstraintKind more consistently

It turned out that we were not being consistent
about our use of isConstraintKind.

It's delicate, because the typechecker treats Constraint and Type as
/distinct/, whereas they are the /same/ in the rest of the compiler
(Trac #11715).

And had it wrong, which led to Trac #15412.  This patch does the
following:

* Rename isConstraintKind      to tcIsConstraintKind
         returnsConstraintKind to tcReturnsConstraintKind
  to emphasise that they use the 'tcView' view of types.

* Move these functions, and some related ones (tcIsLiftedTypeKind),
  from Kind.hs, to group together in Type.hs, alongside isPredTy.

It feels very unsatisfactory that these 'tcX' functions live in Type,
but it happens because isPredTy is called later in the compiler
too.  But it's a consequence of the 'Constraint vs Type' dilemma.

comment:5 Changed 7 months ago by simonpj

Status: newmerge
Test Case: testsuite/tests/typecheck/should_compile/T15412

Wow, that was bad! Thank you for reporting; now fixed.

comment:6 Changed 7 months ago by bgamari

Resolution: fixed
Status: mergeclosed

comment:7 Changed 6 months ago by Iceland_jack

Note: See TracTickets for help on using tickets.