6
votes

I have discovered that I can do this 1 :: Product Int and get Product {getProduct = 1} as a result.

Product is a newtype defined in Data.Monoid. Than I have tried defining my own newtype like so :

newtype Stuff a = Stuff {getStuff :: a} deriving (Show)

But if I try to do 1 :: Stuff Int I get an error :

<interactive>:20:1: error:
* No instance for (Num (Stuff Int)) arising from the literal `1'
* In the expression: 1 :: Stuff Int
  In an equation for `it': it = 1 :: Stuff Int

Do I have to put Num constraint on a or something? Why doesn't this work?

1

1 Answers

15
votes

You can do 1 :: T if and only if T is an instance of Num. 1 :: Product Int works because Product defines an instance instance Num a => Num (Product a) (i.e. if a is an instance of Num, Product a is also an instance of Num).

Do I have to put Num constraint on a or something?

You have to define a Num instance for Stuff Int (or better for Num a => Stuff a).

You can either do this manually (using instance) or automatically using deriving Num and the GeneralizedNewtypeDeriving extension, which will define a Num instance for Num a => Stuff a that acts exactly like the Num instance for the given a.