Skip to content

Don't suggest turning on `DeriveAnyClass` when an instance cannot be derived

Summary

Location of documentation issue: GHC Error Message

Given this example:

class MyClass a where
  myFunc :: a -> Int

data MyExample = MyExample {myBool :: Bool, myInt :: Int}
  deriving (Show, Eq, MyClass)

GHC (correctly) rejects this with this error:

example.hs:5:23: error:
    • Can't make a derived instance of ‘MyClass MyExample’:
        ‘MyClass’ is not a stock derivable class (Eq, Show, etc.)
        Try enabling DeriveAnyClass
    • In the data declaration for ‘MyExample’
  |
5 |   deriving (Show, Eq, MyClass)
  |    

However, it's suggestion to Try enabling DeriveAnyClass is not great, because when one does that:

{-# LANGUAGE DeriveAnyClass #-}

class MyClass a where
  myFunc :: a -> Int

data MyExample = MyExample {myBool :: Bool, myInt :: Int}
  deriving (Show, Eq, MyClass)

GHC now (incorrectly, IMHO), accepts this with the following warning: (At least there is a warning, there didn't use to be, right?)

example.hs:7:23: warning: [-Wmissing-methods]
    • No explicit implementation for
        ‘myFunc’
    • In the instance declaration for ‘MyClass MyExample’
  |
7 |   deriving (Show, Eq, MyClass)
  |  

However, this fails at runtime (!):

*Main> myFunc (MyExample {myBool =True,myInt =5})
*** Exception: example.hs:7:23-29: No instance nor default method for class operation myFunc

Proposed improvements or changes

Don't suggest enabling DeriveAnyClass. Optional: Give a much more comprehensive recommendation that doesn't lead users to write code that throws runtime exceptions in pure code.

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