6

好吧,我正在尝试围绕类型类进行思考,因此我正在尝试为几何向量操作定义一个类型类。我设法让它在组件方面工作,+,-,*,/;但我在点积上苦苦挣扎。

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

显然,我对 (>.) 的实例定义不起作用,因为结果是 type Fractional a,而不是Double

但我不知道如何从类中的声明中获得这种行为。

我想做是:

class GeomVector [a] where
  (>.) :: [a] -> [a] -> a

但这是无效的,因为[a]是类型而不是类型变量。

我希望我能更好地解释这一点,但老实说,我理解得还不够。希望该代码将使我正在努力解决的问题更加明显。

4

1 回答 1

5

这是一个可行的选择:

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)

所以你所有的实例GeomVector都会有一个* -> *Monad。并且方法的类型并没有不必要地限制为Fractional类型,因为您在其中的某个地方进行了划分。

您还可以考虑使您的类尽可能小(>.在类之外创建一个多态函数)以及您真正想要的是否是一个类型类。但这一切都取决于你在设计什么,我不想假设我比你更了解这一点!

于 2012-12-05T00:57:07.093 回答