
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