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

明らかに、 (>.) のインスタンス定義は機能しません。これは、結果の型Fractional aが ではなくであるためDoubleです。

しかし、クラスの宣言からこの動作を取得する方法がわかりません。

私がやりたいことは次のとおりです。

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

しかし、これは[a]型変数ではなく型であるため無効です。

これをもう少しうまく説明できればいいのですが、正直なところ、そうするほど十分に理解できていません。このコードによって、私が何に苦労しているのかがもう少し明確になることを願っています。

4

1 に答える 1

5

動作する可能性のある1つのオプションは次のとおりです。

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種類になります。また、メソッドのタイプは、どこかで分割したからといって、不必要にタイプに制限されることはありません。* -> *MonadFractional

また、クラスをできるだけ小さくすること(>.クラスの外部でポリモーフィック関数を作成すること)や、本当に必要なのが型クラスであるかどうかを検討することもできます。しかし、それはすべてあなたがデザインしているものに依存します、そして私はそれについてあなたよりよく知っているとは思いません!

于 2012-12-05T00:57:07.093 に答える