I've been running through the "Learn You a Haskell" book, and I'm trying to wrap my head around Haskell Type Classes. As practice, I'm trying to create a simple vector type class. The following snippet of code has been giving me some grief (resulting in my first post to StackOverflow):
data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)
class Vector a where
(<*) :: (Num b) => a -> b -> a
instance (Num a) => Vector (Vec2 a) where
Vec2 (x,y) <* a = Vec2 (a*x, a*y)
I get the following error message:
Could not deduce (a~b) from the context (Num a) or from (Num b) bound by the type signature for
<* :: Num b => Vec2 a -> b -> Vec2 a
It seems like the Num being specified in the typeclass should supply the type of a, and Num a spefication in the instance should supply the type of x and y, so why is it complaining? What misconception do I have about this code?
The type of (*) :: Num a => a -> a -> a. But when you are actually trying to use *, you are actually multiplying two unrelated types having Num instances and the compiler is not able to infer that they are same.
To explain it more clearly look at the type of <* and the universal quantification of b
(<*) :: (Num b) => a -> b -> a
What you are saying here is, give me any type having Num instance and I will be able to multiply that with my vector, but what you want to say is something different.
You need to some how say that a in the type Vec2 a is same as b in the type (<*) :: Num b => a -> b -> a, only then you can multiply them together. Here is a solution using typefamilies to ensure this constraint.
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)
class (Num (VectorOf a)) => Vector a where
type VectorOf a :: *
(<*) :: a -> (VectorOf a) -> a
instance (Num a) => Vector (Vec2 a) where
type VectorOf (Vec2 a) = a
Vec2 (x,y) <* a = Vec2 (a*x, a*y)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With