views:

284

answers:

3

Is there a way to "lift" a class instance in Haskell easily?

I've been frequently needing to create, e.g., Num instances for some classes that are just "lifting" the Num structure through the type constructor like this:

data SomeType a = SomeCons a

instance (Num a)=>Num SomeCons a where
    (SomeCons x) + (SomeCons y) = SomeCons (x+y)
    negate (SomeCons x) = SomeCons (negate x)
    -- similarly for other functions.

Is there a way to avoid this boilerplate and "lift" this Num structure automatically? I usually have to do this with Show and other classes also when I was trying to learn existencials and the compiler wouldn't let me use deriving(Show).

+4  A: 

GHC implements what you want : Extensions to the deriving mecanism. These modifications are often shown for future standard language extension (As seen on haskell' wiki)

To Enable this extension, you must use the following pragma

{-# GeneralizedNewtypeDeriving #-}

and then use a deriving on your newtype declaration, as usual

data SomeType a = SomeCons a deriving (Num)
Raoul Supercopter
+17  A: 

The generalized newtype deriving extension is what you want here:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Main where

newtype SomeType a = SomeCons a deriving (Num, Show, Eq)

main = do
  let a = SomeCons 2
      b = SomeCons 3
  print $ a + b

Output:

*Main> main
SomeCons 5
Greg Bacon
Hum... Why this works with newtype but not with data?
Rafael S. Calsaverini
Because a newtype cannot add any constructors or fields—it just rewraps an existing type. This ensures that the extension can work with any class, instead of only the classes you can usually derive for any datatype.
Martijn
+1  A: 

GeneralizedNewtypeDeriving

Don Stewart