5
votes

Consider the following example:

data Dot = Dot Double Double
data Vector = Vector Double Double

First, i would like to overload + operator for Vector addition. If i wanted to overload equality(==) operator, i would write it like:

instance Eq Vector where ...blahblahblah

But I can't find if there is Add typeclass to make Vector behave like a type with addition operation. I can't even find a complete list of Haskell typeclasses, i know only few from different tutorials. Does such a list exist?

Also, can I overload + operator for adding Vector to Dot(it seems rather logical, doesn't it?).

4
Why do you need to distinguish between dots and vectors? As others have mentioned, (+) is in the Num typeclass, but you cannot implement (+) with dots and vectors, since both arguments have to be the same type. If you could think of the two types as being interchangeable, then you could have just one type, and make that type an instance of Num.Boris
Though you are probably looking for Num, the Monoid typeclass may also be of interest to you. See, among other resources, LYAH # monoidsDan Burton

4 Answers

14
votes

An easy way to discover information about which typeclass (if any) a function belongs to is to use GHCi:

Prelude> :i (+)
class (Eq a, Show a) => Num a where
  (+) :: a -> a -> a
  ...
        -- Defined in GHC.Num
infixl 6 +
8
votes

The operator + in Prelude is defined by the typeclass Num. However as the name suggests, this not only defines addition, but also a lots of other numeric operations (in particular the other arithmetic operators as well as the ability to use numeric literals), so this doesn't fit your use case.

There is no way to overload just + for your type, unless you want to hide Prelude's + operator (which would mean you have to create your own Addable instance for Integer, Double etc. if you still want to be able to use + on numbers).

6
votes

You can write an instance Num Vector to overload + for vector addition (and the other operators that make sense).

instance Num Vector where
    (Vector x1 y1) + (Vector x2 y2) = Vector (x1 + x2) (y1 + y2)
    -- and so on

However, note that + has the type Num a => a -> a -> a, i.e. both operands and the result all have to be the same type. This means that you cannot have a Dot plus a Vector be a Dot.

While you can hide Num from the Prelude and specify your own +, this is likely to cause confusion and make it harder to use your code together with regular arithmetic.

I suggest you define your own operator for vector-point addition, for example

(Dot x y) `offsetBy` (Vector dx dy) = Dot (x + dx) (y + dy)

or some variant using symbols if you prefer something shorter.

4
votes

I sometimes see people defining their own operators that kind of look like ones from the Prelude. Even ++ probably uses that symbol because they wanted something that conveyed the idea of "adding" two lists together, but it didn't make sense for lists to be an instance of Num. So you could use <+> or |+| or something.