2

さまざまな次元のベクトル量の数値積分をモデル化してみようと考え、型クラスが最適であると考えました。2 つの値の差を定義し、(導関数を取得するために) 乗数でスケーリングし、距離関数を取得できるようにする必要がありました。

これまでのところ、私は持っています:

class Integratable a where
    difference :: a -> a -> a
    scale :: Num b => a -> b -> a
    distance :: Num b => a -> a -> b

data Num a => Vector a = Vector1D a | Vector2D a a

instance Num a => Integratable (Vector a) where
    difference (Vector1D x1) (Vector1D x2) = Vector1D (x1 - x2)
    scale (Vector1D x) m = Vector1D (x * m)
    distance (Vector1D x1) (Vector1D x2) = x1 - x2
    difference (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
    scale (Vector2D x y) m = Vector2D (x * m) (y * m)
    distance (Vector2D x1 y1) (Vector2D x2 y2) = sqrt((x1-x2)*(x1-x2)
                                                      + (y1-y2)*(y1-y2))

残念ながら、解決方法がわからない問題がいくつかあります。まず、scale関数でエラーが発生します。GHCはそれを伝えることができず、互換性がmあります.1つのケースではインスタンスでx厳格な型制限Numが与えられ、Vector別のケースでは型で与えられているためです...それを指定して同じ型にする方法はありますxm?

x(実際には、とmが両方ともであっても、同じNumではない可能性があることに気付きました。どうすればこれを指定できますか? でわからない場合は、 を使用しても問題ありませんが、むしろ一般的なままにしておきます。) NumNumDouble

にも同様の問題がありdistanceます。と互換性のある値が含まれるNumインスタンス定義で判断できないため、戻り値の型を に指定しようとすると失敗します。ab

4

2 に答える 2

1

編集: HaskellWiki の機能依存関係に関する記事は、私が見つけることができる最良の形式で重要な情報を提供しているように思われるので、ここでの回答の代わりにそれを読むことをお勧めします。ただし、残りのコンテンツを削除するつもりはありません。なぜなら、ここで FD が役立つ理由が明確になるからです (希望します)。


デイブが指摘した定義の問題のグループ化とは別に...

x(実際には、とmが両方ともであっても、同じNumではない可能性があることに気付きました。どうすればこれを指定できますか? でわからない場合は、 を使用しても問題ありませんが、むしろ一般的なままにしておきます。) NumNumDouble

実際、これが主な問題です。Integerたとえば、 a にaを掛けることはできませFloatん。x実際には、とmイン スケール が同じタイプである必要があります。

また、距離についても同様の問題が発生し、議論がsqrt必要な追加の複雑さがありFloatingます。ですから、それについてもどこかで言及する必要があると思います。(インスタンス上で最も可能性が高いと思います)。

編集: OK、値でsqrtのみ機能するため、必要に応じて s をs にFloatingアップキャストする型クラスをロールできます。FloatDouble

もう 1 つのアイデアは、 typeclass を持つことですScalable

data Vector a = Vector1D a | Vector2D a a deriving (Show)                       

class Scalable a b | a -> b where
  scale :: a -> b -> a

instance (Num a) => Scalable (Vector a) a where
  scale (Vector1D x)   m = (Vector1D (x * m))
  scale (Vector2D x y) m = (Vector2D (x * m) (y * m))

これは、 の定義でいわゆる関数依存を使用しますScalable。実際、その構文を覚えようとして、このリンクを見つけました...だから、役立つという私の劣った試みを無視して、そこにある品質情報を読むべきだと思います. ;-)

これを使用して元の問題を解決できるはずだと思います。

于 2009-12-22T15:44:41.573 に答える
0

2 番目のエラーを修正するには、インスタンス宣言で定義を並べ替える必要があると思います。最初に の 2 つの方程式difference、次に の方程式scale、次に の両方の方程式がありdistanceます。

于 2009-12-22T15:28:56.253 に答える