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
.