10

The codes looks like this:

class MyAnd a where
  myAnd :: (Show a) => a -> a -> String
  x `myAnd` y = (show x) ++ " and " ++ (show y)

data TrafficLight = Red | Yellow | Green deriving(Show, MyAnd)

Here MyAnd is a type class which has a function myAnd, I thought it is generic and the only constraint is the a has to has an instance of Show class..

In the TrafficLight type, it already derived from Show type class. However, when I compiled the codes, the compiler complains

    Can't make a derived instance of ‘MyAnd TrafficLight’:
      ‘MyAnd’ is not a derivable class
    In the data declaration for ‘TrafficLight’
Failed, modules loaded: none.

Does anyone have ideas about this?

Hanfei Sun
  • 45,281
  • 39
  • 129
  • 237

3 Answers3

10

You can't use deriving with user-defined classes. Usually deriving automatically generates code for the given class's methods, which is only possible because the compiler knows what the methods are supposed to do and can thus generate suitable implementations based on your type's structure. This is obviously not possible for user-defined classes as the compiler has no way of knowing how the methods are supposed to behave.

In your case it looks like all you want is to use the default implementations of the one method your class has, so no implementation would need to be generated by the compiler. Of course that means that deriving isn't necessary at all and you can just use an instance declaration without a body.

PS: If you'll always want to use the default implementation of the method, it might make the most sense not to use a class at all, but just define myAnd as a function.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 1
    True, the compiler does not know what the methods are supposed to do. But maybe a worthwhile addition to the language would be a way to tell it. Related: http://stackoverflow.com/a/3864801/524504 – masterxilo Dec 13 '16 at 19:44
9

For this specific problem, you can simply avoid defining a custom class:

data TrafficLight = Red | Yellow | Green deriving Show

myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)

Now, myAnd is applicable to TrafficLights (as well as all the other Showable types).

chi
  • 111,837
  • 3
  • 133
  • 218
0

Found this question while trying to figure out how to use GHC's DeriveAnyClass extension, which had only been out for three weeks back when this was asked.

Using it, the following works as you'd expect:

{-# LANGUAGE DeriveAnyClass #-}

class Show a => MyAnd a where
    myAnd :: a -> a -> String
    x `myAnd` y = (show x) ++ " and " ++ (show y)

data TrafficLight = Red | Yellow | Green deriving (Show, MyAnd)

Should be used with caution though, as it will literally derive any class, creating empty instances when necessary.

lvsz
  • 71
  • 3