Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Typeclass Type Constraints and Deduction

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?

like image 917
mysterymath Avatar asked Dec 12 '25 18:12

mysterymath


1 Answers

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)
like image 197
Satvik Avatar answered Dec 16 '25 02:12

Satvik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!