Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I omit the constructor when referring to newtype wrapped number types?

On page 321 of Real World Haskell

There are these codes,

...

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype AInt = A { unA::Int }
    deriving (Show, Eq, Num)

instance Monoid AInt where
    mempty = 0

My confusion is why it is

mempty = 0

but not

mempty = A 0

?


I also noticed that both

ghci> 0 :: AInt

and

ghci> A 0 :: AInt

give me the same response

A { unA = 0 }

Would someone please tell me what is the difference between theses two?

like image 434
Znatz Avatar asked Apr 16 '13 04:04

Znatz


1 Answers

The trick here is with the GeneralizedNewtypeDeriving extension. In particular, this lets us derive any class for a newtype as long as the underlying type is an instance. All this does is copy over the instance from the old type to the new type.

In this particular case, AInt derives Num. This means that AInt is an instance of Num using the same code as Int (with everything wrapped in A constructors as appropriate). This includes Int's fromInteger function.

The fromInteger function is defined in terms of Int's fromInteger, looking something like this:

fromInteger i = A (fromInteger i)

Since 0 is polymorphic--it has the type 0 :: Num a => a--it's a valid constant for any type in Num. Thanks to the newtype deriving, this includes AInt, using the fromInteger function above. This means there is really no difference between 0 :: AInt an A 0 :: AInt.

like image 162
Tikhon Jelvis Avatar answered Sep 22 '22 21:09

Tikhon Jelvis