Skip to content

Deriving via DeriveAnyClass not behaving the same as an emply instance declaration

I've opened a question on StackOverflow describing the issue. I'll copy it here:


I have the following code

{-# LANGUAGE PolyKinds, DefaultSignatures, FlexibleContexts, DeriveAnyClass, DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}
module DeriveTest where

import GHC.Generics

class GenericClass a m where
instance GenericClass f m => GenericClass (M1 i c f) m
instance Condition a m => GenericClass (K1 i a) m

class Condition (a :: k) (m :: * -> *) where
instance (Condition a m, Condition b m) => Condition (a b) m
instance {-# OVERLAPPABLE #-} Condition (a :: k) m

class Class (e :: (* -> *) -> *) where
    classF :: e m -> ()
    default classF :: GenericClass (Rep (e m)) m => e m -> ()
    classF = undefined

It defines the class Class of types that have a higher-kinded type as a parameter. It also defines a generic way to derive an instance of that class. Now if I declare a new datatype like this, and try to derive an instance of Class

data T a m = T
    { field :: a }
    deriving (Generic, Class)

I get the following error:

    * Overlapping instances for Condition a m
        arising from the 'deriving' clause of a data type declaration
      Matching instances:
        instance [overlappable] forall k (a :: k) (m :: * -> *).
                                Condition a m
        instance forall k1 k2 (a :: k1 -> k2) (m :: * -> *) (b :: k1).
                 (Condition a m, Condition b m) =>
                 Condition (a b) m
      (The choice depends on the instantiation of `a, m'
       To pick the first instance above, use IncoherentInstances
       when compiling the other instance declarations)
    * When deriving the instance for (Class (T a))
   |
22 |     deriving (Generic, Class)
   |                        ^^^^^
                            

The error sort of makes sense I guess. The instance really does depend on the instantiation of a. However, if I just write an empty instance like this:

data T a m = T
    { field :: a }
    deriving (Generic)
instance Class (T a) -- works

It works. Why? And how can I make it behave the same with the deriving statement?


Ryan Scott suggested I open a ticket and that the issue probably isn't with the deriving mechanisms. Still, I chose to keep the title because that's what the original problem was and I've seen similar issues before

Edited by Darwin226
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information