# [Haskell-cafe] Decoupling OpenAL/ALUT packages from OpenGL

Neil Brown nccb2 at kent.ac.uk
Mon May 11 06:04:07 EDT 2009

```Sven Panne wrote:
> Regarding Functor/Applicative: The obvious instances for e.g. a 2-dimensional
> vertex are:
>
>    data Vertex2 a = Vertex2 a a
>
>    instance Functor Vertex2 where
>       fmap f (Vertex2 x y) = Vertex2 (f x) (f y)
>
>    instance Applicative Vertex2 where
>       pure a = Vertex2 a a
>       Vertex2 f g <*> Vertex2 x y = Vertex2 (f x) (g y)
>
> They fulfill all required laws, but are these the only possible instances? If
> not, are they at least the most "canonical" ones in a given sense? And
> finally: Does somebody have a real-world example where the Applicative
> instance is useful? Usages of the Functor instance are much more obvious for
> me.
>
I'd say those are the right instances.  Some obvious uses (perhaps more
useful for Vector2 than Vertex2, but still) are:

liftA2 (+) (Vertex2 1 3) (Vertex2 4 5) == Vertex2 5 8
pure 0 == Vertex2 0 0

The latter being a useful shorthand to get a vertex for the origin.
Also, if you define Foldable:

foldl1 (+) . liftA2 (*) v w == dotProduct v w

The useful thing being that that definition of dotProduct is the same
for 2-, 3- and 4- dimensional things, and for vertexes and vectors.  So
Traversable (no harm, although I'd have to reach further for an example
for this).  I guess the tricky decision might be whether to provide a
Num instance  (again, probably more suitable for Vector2)?

instance Num a => Num (Vertex2 a) where
(+) = liftA2 (+)
(-) = liftA2 (-)
(*) = liftA2 (*)
abs = fmap abs
signum = fmap signum
negate = fmap negate
fromInteger = pure . fromInteger

Even if you don't want to define Num, note how easy having the
Applicative instance makes defining some of the operators :-)

Thanks,

Neil.
```