0

私は次の型クラスインスタンスを持っています:

type Scalar = Double
data Vector = Vector [Double] deriving (Show, Eq)

instance Num Vector where
  (+) (Vector xs) (Vector ys) = Vector (zipWith (+) xs ys)
  (-) (Vector xs) (Vector ys) = Vector (zipWith (-) xs ys)
  (*) (Vector xs) (Vector ys) = Vector (zipWith (*) xs ys)

instance Fractional Vector where
  (/) (Vector xs) (Vector ys) = Vector (zipWith (/) xs ys)

dot :: Vector -> Vector -> Vector
dot (Vector v1) (Vector v2) = sum $ v1 + v2

しかし、ドット方式はタイプチェックを行いません。Vectorクラスにあるのに、+メソッドを使用できないと思います。

 No instance for (Num [Double])
      arising from a use of `+'
    Possible fix: add an instance declaration for (Num [Double])
    In the second argument of `($)', namely `v1 + v2'
    In the expression: sum $ v1 + v2
    In an equation for `dot':
        dot (Vector v1) (Vector v2) = sum $ v1 + v2

編集:それは恥ずかしいことでした。

4

2 に答える 2

2

(数学的には、通常、このようなベクトルの乗算(または除算)は定義しません。2つのベクトルを組み合わせるために外積または内積を使用します。)

とにかく、必要に応じて、インスタンス関数を使用してドット積を定義できます。

dot :: Vector -> Vector -> Scalar
dot vector1 vector2 = let (Vector list3) = vector1 * vector2 in
   sum list3

タイプに注意してくださいVector -> Vector -> Scalar。結果のタイプはScalar、乗算されたエントリを合計すると、数値でいっぱいのベクトルではなく、数値が1つしかないためです。また、2つの引数vector1vector2はベクトルであるため、として記述されVector somelistます。

Doubleのリストを乗算できないため、コンストラクターがそのまま残っているを使用*しました。元のコードでは、Doubleのリストを追加(または乗算)しようとしましたが、インスタンスは未加工の[Double]ではなく、Vectorでの加算と乗算のみを定義しているため、機能しません。vector1vector2Vector

節ではlet、この乗算の結果を取得し、それを。と照合しましたVector list3。つまり、これlist3 Doubleのリストなので、sum関数を使用できます。sumはDoubleのリストで定義されていますが、ベクトルでは定義されていないため、sumonを直接使用しても機能しvector1 * vector2ませんでした。

例:

> dot (Vector [1, 10, 100]) (Vector [1, 2, 3])
321.0
于 2012-12-10T07:19:41.310 に答える
1

問題は

dot :: Vector -> Vector -> Vector
dot (Vector v1) (Vector v2) = sum $ v1 + v2

タイプが間違っている、代わりにあなたが望む

dot :: Vector -> Vector -> Double
dot (Vector v1) (Vector v2) = sum $ zipWith (*) v1 v2

また、ドット積が必要だと思うので、をに変更し+たことにも注意してください。*

dot :: Vector -> Vector -> Double
dot v1 v2 = let Vector ls = v1 * v2 in sum ls

Numインスタンスを使用するVector

于 2012-12-10T05:33:46.873 に答える