Alright, I'm trying to wrap my head around typeclasses, and so I'm trying to define a typeclass for geometric vector operations. I managed to get it working for component-wise +,-,*,/;
but I'm struggling with the dot product.
class GeomVector a where
(>+) :: a -> a -> a
(>-) :: a -> a -> a
(>*) :: a -> a -> a
(>/) :: a -> a -> a
(>.) :: a -> a -> Double
data Vector a = Vec [a]
deriving Show
instance (Fractional a) => GeomVector (Vector a) where
(>+) (Vec u) (Vec v) = Vec $ zipWith (+) u v
(>-) (Vec u) (Vec v) = Vec $ zipWith (-) u v
(>*) (Vec u) (Vec v) = Vec $ zipWith (*) u v
(>/) (Vec u) (Vec v) = Vec $ zipWith (/) u v
(>.) (Vec u) (Vec v) = sum $ u >* v
Obviously my instance definition for (>.) won't work because the result is of type Fractional a
, not Double
.
But I don't know how to get this behavior from the declaration in the class.
What I'd like to do is:
class GeomVector [a] where
(>.) :: [a] -> [a] -> a
But this is invalid because [a]
is a type and not a type variable.
I wish I could explain this a little better, but I honestly don't understand enough to do so. Hopefully the code will make it a little more obvious what I'm struggling with.
Here's one option that could work:
class GeomVector v where
(>+) :: Num a=> v a -> v a -> v a
(>-) :: Num a=> v a -> v a -> v a
(>*) :: Num a=> v a -> v a -> v a
(>/) :: Fractional a=> v a -> v a -> v a
(>.) :: Num a=> v a -> v a -> a
data Vector a = Vec { vecList :: [a] }
deriving Show
instance GeomVector Vector where
(>+) (Vec u) (Vec v) = Vec $ zipWith (+) u v
(>-) (Vec u) (Vec v) = Vec $ zipWith (-) u v
(>*) (Vec u) (Vec v) = Vec $ zipWith (*) u v
(>/) (Vec u) (Vec v) = Vec $ zipWith (/) u v
(>.) u v = sum $ vecList (u >* v)
So all your instances of GeomVector
will have a kind * -> *
like the Monad
class. And the types of the methods are not unnecessarily restricted to Fractional
types just because you divide somewhere in there.
You might also consider making your class as small as possible (make >.
a polymorphic function outside of the class) and whether what you really want is a type class to begin with. But all that depends on what you're designing, and I don't want to presume that I know better than you about that!
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