I don't see why 'dot' part will not work.
class Vector a where
add, minus, cross :: a -> a -> a
dot :: Num b => a -> a -> b
data Vector2D a = Vector2D a a deriving (Read)
instance Num a => Vector (Vector2D a) where
add (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 + x2) (y1 + y2)
minus (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
dot (Vector2D x1 y1) (Vector2D x2 y2) = x1*x2 + y1*y2
The error message is:
Couldn't match expected type ‘b’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the instance declaration at example.hs:9:10
‘b’ is a rigid type variable bound by
the type signature for
dot :: Num b => Vector2D a -> Vector2D a -> b
at example.hs:12:3
Relevant bindings include
y2 :: a (bound at example.hs:12:37)
x2 :: a (bound at example.hs:12:34)
y1 :: a (bound at example.hs:12:20)
x1 :: a (bound at example.hs:12:17)
dot :: Vector2D a -> Vector2D a -> b (bound at example.hs:12:3)
In the first argument of ‘(*)’, namely ‘x1’
In the first argument of ‘(+)’, namely ‘x1 * x2’
I look at the type of dot and it is dot :: (Num b, Vector a) => a -> a -> b. How can I make it right?
The problem is that the type signature
dot :: Num b => a -> a -> b
means that dot needs to be able to return any numeric type, regardless what the vector type is, while the expression x1*x2 + y1*y2 will only return the type that was put into the vectors.
To fix that you can use a type family to connect a single scalar type to each vector type:
{-# LANGUAGE TypeFamilies #-}
class Vector a where
type ScalarOf a
add, minus, cross :: a -> a -> a
dot :: a -> a -> ScalarOf a
data Vector2D a = Vector2D a a deriving (Read)
instance Num a => Vector (Vector2D a) where
type ScalarOf (Vector2D a) = a
add (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 + x2) (y1 + y2)
minus (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
dot (Vector2D x1 y1) (Vector2D x2 y2) = x1*x2 + y1*y2
An alternative method is to use a multiparameter type class, probably with a functional dependency.
I also want to mention that cross products essentially only make sense for 3-dimensional vectors. (I've heard that you can make them work for 7 dimensions, or trivially for 1.)
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