# [Haskell-cafe] Num instances for 2-dimensional types

Job Vranish jvranish at gmail.com
Mon Oct 5 09:07:55 EDT 2009

```You are in luck!

Such an instance is very simple with Applicative. If the type you want a Num
instance for is a member of the Applicative type class you can define it
like this:

instance (Num a) => Num (Vector2 a) where
a + b = pure (+) <*> a <*> b
a - b = pure (-) <*> a <*> b
a * b = pure (*) <*> a <*> b
negate a = pure negate <*> a
abs a = pure abs <*> a
signum = fmap signum
fromInteger = pure . fromInteger

If you want to define a Num instance for _all_ applicatives, you can do this
(you'll need a couple extensions):

instance (Num a, Applicative f, Eq (f a), Show (f a)) => Num (f a) where
a + b = pure (+) <*> a <*> b
a - b = pure (-) <*> a <*> b
a * b = pure (*) <*> a <*> b
negate a = pure negate <*> a
abs a = pure abs <*> a
signum = fmap signum
fromInteger = pure . fromInteger

I am currently working on a vector and matrix library for haskell that uses
instances of this form, which you can find here:
http://github.com/jvranish/VectorMatix.  The matrix half is very unfinished,
but the vector half is pretty much done.

Applicative is a pretty fantastic typeclass, it's definitly worth the time
to figure out how it works.

However, this technique won't work with tuples as they don't behave as
Functors in the way you would like. (too many type parameters, tuples don't
force all elements to be the same type so maps don't work, etc...)

Hope that helps :)

- Job

On Mon, Oct 5, 2009 at 8:40 AM, Sönke Hahn <shahn at cs.tu-berlin.de> wrote:

> Hi!
>
> I often stumble upon 2- (or 3-) dimensional numerical data types like
>
>    (Double, Double)
>
> or similar self defined ones. I like the idea of creating instances for Num
> for
> these types. The meaning of (+), (-) and negate is clear and very
> intuitive, i
> think. I don't feel sure about (*), abs, signum and fromInteger. I used to
> implement
>
>    fromInteger n = (r, r) where r = fromInteger n
>
> , but thinking about it,
>
>    fromInteger n = (fromInteger n, 0)
>
> seems very reasonable, too.
>
> Any thoughts on that? How would you do it?
>
> btw: These are two examples i looked at in hackage:
> Data.Complex.Complex (which is special, cause it is mathematically defined,
> what (*), abs, signum and fromInteger should do (i think))
>
> and
>
> Physics.Hipmunk.Common.Vector
> (
> )
>
>
> Sönke
> _______________________________________________