Here are some definitions I wrote, to avoid mixing currencies
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
data EUR
data USD
newtype Amount a = Amount Double deriving (Fractional, Num, Show)
eur :: Double -> Amount EUR
eur = Amount
usd :: Double -> Amount USD
usd = Amount
usd 34 + usd 3
type checks as expectedusd 33 + eur 33
is a compilation error as expected- I'm surprised but
usd 33 + 3
is OK according to the compiler. Something I wanted to avoid, and don't understand. I suspect it is becauseNum
instance, but then what is the difference with the second case?
Can you explain why usd 33 + 3
compiles and if it is possible to make the type-checker reject this expression.
Numbers in Haskell have lots of implicitness. Mentally, you ought to replace every number literal like
3
withfromInteger 3
. SinceAmount
usesGeneralizedNewtypeDeriving
to be part of theNum
typeclass, it inherits afromInteger
instance. So the compiler is doing this