我想创建一个数据类型,它可以采用长度为2或3的元组,并且应该包含派生Num和Ord的类型。然后,我想在我的类型类实例中对这个元组的长度进行模式匹配,以便我可以根据元组长度决定使用哪个函数。看看下面的不可编译的伪代码。至少有两个问题:
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 x@(_,_) y@(_,_) = x `dominates2` y -- takes two tuples of length 2
dominates x@(_,_,_) y@(_,_,_) = x `dominates3` y -- takes two tuples of length 3
更新
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
}
instance Eq Ind where
(Ind{ fitnesses = I2 x@(a1,a2) }) == (Ind{ fitnesses = I2 y@(b1,b2) }) = indCmp2 x y == EQ
instance Ord Ind where
(Ind{ fitnesses = I2 x@(a1,a2) }) `compare` (Ind{ fitnesses = I2 y@(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
这个编译。如果我只想要Eq
,为什么需要制作Ord
的实例?如果没有Eq实例,编译器会抱怨&#34;没有(Eq Ind)&#34;的实例。
答案 0 :(得分:2)
您可以提供2元组和3元组的实例。
class Dominates a where
dominates :: a -> a -> bool
instance (Num a, Num b) => Dominates (a,b) where
dominates = dominates2 -- takes two tuples of length 2
instance (Num a, Num b, Num c) => Dominates (a,b,c) where
dominates = dominates3 -- takes two tuples of length 3
但是,我想知道这是否是你真正需要的。
您可以在所有可能的情况下需要模式匹配,如下所示。这里不需要课程。
dominates :: Ind -> Ind -> Bool
dominates (Ind{ fitnesses = I2 (a1,a2) })
(Ind{ fitnesses = I2 (b1,b2) }) = ...
dominates (Ind{ fitnesses = F2 (a1,a2) })
(Ind{ fitnesses = F2 (b1,b2) }) = ...
dominates (Ind{ fitnesses = I3 (a1,a2,a3) })
(Ind{ fitnesses = I3 (b1,b2,b3) }) = ...
dominates (Ind{ fitnesses = F3 (a1,a2,a3) })
(Ind{ fitnesses = F3 (b1,b2,b3) }) = ...
dominates _ _ = error "incompatible Ind values!"
示例:
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
} -- no deriving Ord here, we want to define it manually
instance Ord Ind where
(Ind{ fitnesses = I2 x }) `compare` (Ind{ fitnesses = I2 y }) = indCmp2 x y
-- other cases here