Overloading via a Haskell type class enables bounded polymorphism over the instance types. For example
(+) :: Num a => a → a → a
is polymorphic, but bounded over types a
with a Num
instance.
So one answer could be: use operator overloading, when you want to write code, which abstracts over the operator in a type safe way. For example:
dot :: Num a => (a, a) → a
dot (x, y) = x*x + y*y
However there are alternatives to be argued about, e.g. one may prefer to pass explicit arguments instead of implicit type class dictionaries:
dot :: (a→a) → (a→a) → (a, a) → a
dot (+) (*) (x,y) = x*x + y*y
For considering why the Prelude (+)
is not defined for String
, you can look at the Num
type class:
class Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
Although, it's not clear from documentation, I think a Num
type is supposed to be a ring with some extra properties. There is some discussion about Num
on stack overflow.
However, the Monoid
type class has the correct structure:
class Monoid m where
mappend :: m → m → m -- Has to be associative.
mempty :: m -- Has to be neutral to mappend.
(<>) = mappend
For example, "foo" <> "bar"
evaluates to "foobar"
and "foo" <> mempty
evaluates to "foo"
.