The class Num defines the method functions like (+), (-), (*), negate, ...
But they are actually different concepts.
We often meet situations that we want an addition for some type, but
not a multiplication. For example:
data Vec3 = Vec3 Float Float Float
The additive (and subtractive) operation is obvious, but not for a
multiplication.
Note
(*) :: a -> a -> a -- not avaliable for a Vec3
scale :: Float -> Vec3 -> Vec3
dot :: Vec3 -> Vec3 -> Float
We cannot define a (+) alone for a type, so we got many different functions
from different libs, like mappend, mplus, plus, (<+>), (.+.), (+.), which all reads
"plus".
My opinion is that the methods of Num should be seperated into different type
classes, so we don't need to invent a new symbol for a new lib.
A feasible design is:
import Prelude hiding ( Num (..), Monoid (..), sum )
class SemiGroup a where
(+) :: a -> a -> a
class SemiGroup a => Monoid a where
zero :: a
class Monoid a => Group a where
negate :: a -> a
(-) :: a -> a -> a
x - y = x + negate y
negate x = zero - x
class Group a => Ring a where -- not sure about the name ...
(*) :: a -> a -> a
class Ring a => Num a where
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
sum :: (Foldable t, Monoid a) => t a -> a
sum = foldl' (+) zero
-- for compatibility
mempty = zero
mappend = (+)
mconcat = sum