長さ2または3のタプルをとり、NumおよびOrdを派生する型を含むデータ型を作成したいとします。次に、タプルの長さに基づいてどの関数を使用するかを決定できるように、型クラスインスタンス内のこのタプルの長さをパターンマッチします。下記の非コンパイル可能な疑似コードを見てください。少なくとも2つの問題があります。インスタンス内のタプル長のハスケルパターン一致
-
Dominates
は、私は、例えばタプルを取得する方法がわからない クラス導出ではありません
fitnesses
を呼び出して、インスタンスでパターンマッチングが行われるときに変数をデータ型から取得します。
コード:
data Fits = I2 (Int, Int) | F2 (Float, Float) | I3 (Int, Int, Int) | F3 (Float, Float, Float)
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
} deriving (Dominates)
class Dominates a where
dominates :: a -> a -> bool
instance Dominates Ind where
dominates [email protected](_,_) [email protected](_,_) = x `dominates2` y -- takes two tuples of length 2
dominates [email protected](_,_,_) [email protected](_,_,_) = x `dominates3` y -- takes two tuples of length 3
を更新:
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
}
instance Eq Ind where
(Ind{ fitnesses = I2 [email protected](a1,a2) }) == (Ind{ fitnesses = I2 [email protected](b1,b2) }) = indCmp2 x y == EQ
instance Ord Ind where
(Ind{ fitnesses = I2 [email protected](a1,a2) }) `compare` (Ind{ fitnesses = I2 [email protected](b1,b2) }) = indCmp2 x y
indCmp2 :: (Num a, Ord a) => (a, a) -> (a, a) -> Ordering
indCmp2 x y
| a0 < b0 = LT
| a0 > b0 = GT
-- Can assume (fst x) == (fst y) beneath
| a1 < b1 = LT
| a1 > b1 = GT
| a1 == b1 = EQ
where
a0 = fst x
a1 = snd x
b0 = fst y
b1 = snd y
これがコンパイルされます。 Ord
だけが必要な場合、なぜEq
のインスタンスを作成する必要がありますか? Eq-instanceがなければ、コンパイラは「(Eq Ind)のインスタンスはありません」と文句を言います。
最初の例では 'Ind'レコードの' fitness'フィールドを抽出しません。インスタンスを使ってそれを行う方法はありますか?私はOrdのインスタンスを派生させたい。 – tsorn
@tsornわかりません。 'x'が' Ind''型の値なら 'fitness x'はフィールドの値です。なぜあなたはここでクラスを使う必要がありますか? – chi
最初の例では、 'Dominates'は' Ind'のインスタンスを持たないので、 'Ind'はそれを派生できません。 2番目の例はうまくいきますが、Ordを派生させたい場合はinstanceを使う必要があると思います。トップポストに別の例を追加しました。 – tsorn