複数のデータ型があり、それぞれが複数の実装を持つことができるHaskellコードを記述しようとしています。これを行うには、それぞれのデータ型をclass
として定義します。そのメソッドは、関連するコンストラクタとセレクタです。次に、指定されたコンストラクタとセレクタに関して、そのクラスのメンバに対してすべての操作を実装します。お楽しみタイプ!複数のインスタンス宣言の解決
例えば、恐らくA
はSparsePoly
又はDensePoly
とB
として表現を有することができる(方法getCoefficients
とmakePolynomial
有する)多項式クラスがあるとすることができる(方法getReal
、getImag
とmakeComplex
有する)複素数クラスでありますComplexCartesian
またはComplexPolar
で表されます。
私は以下の最小限の例を再現しました。私は2つのクラスA
とB
を持っています。両方のクラスのすべてのインスタンスをNum
のインスタンスに自動的に作成したい(これには、FlexibleInstances
とUndecidableInstances
拡張が必要です)。私はA
またはB
のいずれかを持っているとき、これは正常に動作しますが、私は両方でコンパイルしようとすると、私は次のエラーを取得する:
Duplicate instance declarations:
instance [overlap ok] (A a, Num x, Show (a x), Eq (a x)) =>
Num (a x)
-- Defined at test.hs:13:10-56
instance [overlap ok] (B b, Num x, Show (b x), Eq (b x)) =>
Num (b x)
-- Defined at test.hs:27:10-56
私は「重複インスタンス宣言」というメッセージがデータ型のためであると仮定しますA
とB
の両方のインスタンスにすることができます。私はそれをしないことを約束したり、型が両方のクラスのインスタンスである場合に使用するデフォルトのクラスを指定したりすることを約束することができるようにしたい。
これを行う方法はありますか(別のタイプの拡張ですか?)、これは私が悩んでいるものですか?
は、ここに私のコードです:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
class A a where
fa :: a x -> x
ga :: x -> a x
data AImpl x = AImpl x deriving (Eq,Show)
instance A AImpl where
fa (AImpl x) = x
ga x = AImpl x
instance (A a, Num x, Show (a x), Eq (a x)) => Num (a x) where
a1 + a2 = ga (fa a1 + fa a2)
-- other implementations go here
class B b where
fb :: b x -> x
gb :: x -> b x
data BImpl x = BImpl x deriving (Eq,Show)
instance B BImpl where
fb (BImpl x) = x
gb x = BImpl x
instance (B b, Num x, Show (b x), Eq (b x)) => Num (b x) where
-- implementations go here
編集:は、自分自身を明確にするために、私はこの技術を用いて実用的なコードを記述するつもりはありませんよ。タイプシステムとエクステンションの理解を深めるための練習としてやっています。
関連する:[私はどのように書いていますか?もし型付きaなら、この定義ではaもbのインスタンスです。 "](http://stackoverflow.com/a/3216937/98117)。 – hammar