13

i have this

data Something = Something Integer deriving (MyClass, Show)

class MyClass a where   
    hello :: MyClass a => a -> a

instance MyClass Integer where
    hello i = i + 1

main = print . hello $ Something 3

but MyClass isn't derivable. Why?

vek
  • 1,523
  • 10
  • 18
  • 7
    You don't need the `MyClass a =>` part of the type signature for `hello`; it's implied by the fact that `a` is brought into scope via a class declaration of the form `class MyClass a where ...`. – Antal Spector-Zabusky Feb 07 '13 at 16:33
  • Have a look at the [GHC users guide about deriving](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extensions-to-the-deriving-mechanism). – Chris Martin Feb 21 '17 at 23:53

2 Answers2

13

GHC cannot magically derive instances for arbitrary data types. However, it can make use of the fact that newtype declarations create a new name for the same underlying type to derive instances for those using the GeneralizedNewtypeDeriving extension. So, you could do something like this:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype Something = Something Integer deriving (MyClass, Show)

class MyClass a where
    hello :: MyClass a => a -> a

instance MyClass Integer where
    hello i = i + 1

main = print . hello $ Something 3

The reason GHC cannot derive the new instance is that it does not know what the instance should be. Even if your data type only has one field, it may not necessarily be the same as that field. The ability to derive instances for newtypes is convenient, since they are usually used to provide different behaviours for certain typeclasses or as a way to use the type system to separate things that have the same type but different uses in your code.

sabauma
  • 4,243
  • 1
  • 23
  • 23
  • 2
    `newtype` deriving is convient but not safe with its current implementation. I say only use in early versions of your code. The new `default`/generic framework is more general and safe (but also clunkier), so use that instead when possible. – Philip JF Feb 07 '13 at 17:19
  • @PhilipJF what is unsafe about the current implementation of newtype deriving? – Dan Burton Feb 07 '13 at 18:45
  • 4
    @DanBurton 1. it does not interact correctly with type equalities, see my blog http://joyoftypes.blogspot.com/2012/08/generalizednewtypederiving-is.html and lets you type `unsafeCoerce` 2. it breaks modules that rely on "single instance property" (I think we should give this up, but what ever) with just Haskell 98 since you can define `class IntIso a where intIso :: f Int -> f a` with instance `Int` and `newtype X = X Int deriving IntIso` which lets you coerce between `Set Int` and `Set X` but `X` might have a different ordering relation and so can break Data.Set . – Philip JF Feb 07 '13 at 18:54
  • It's possible to make a safe, but less powerful, `NewtypeDeriving`. – augustss Feb 07 '13 at 20:37
  • 2
    All the evil examples of `NewtypeDeriving` involve somebody setting out to do evil. If you use it sanely, it won't be a problem. And it _is_ getting fixed in newer GHC anyway. – sclv Feb 07 '13 at 21:51
  • 2
    BTW, it *has* been fixed. The fix, unfortunately, ends up rejecting a lot of perfectly good code, but at least it avoids the type safety problem. – dfeuer Dec 29 '15 at 23:07
13

You may want to have a look at the GHC documentation on Generic Programming.
You need to create a class that can work on a generic representation of arbitrary types. I don't think the specific example you gave is reasonable for a derivable class.

asm
  • 8,758
  • 3
  • 27
  • 48
  • 2
    +1 Glad someone brought that up as a response to this question. Do you fancy exapanding into an example of one where it _is_ reasonable? – AndrewC Feb 07 '13 at 17:05
  • @AndrewC unfortunately I don't understand it well enough to expand that far. If you do feel free to edit the question. – asm Feb 07 '13 at 17:11
  • here is an example of a generic "Default" class (a type defaults to its first construct): http://pastebin.com/amgQRvFD (I'm learning generic programming myself, I don't know if this is the best way) – sam boosalis Oct 30 '14 at 04:25