实例

时间:2016-05-09 11:16:49

标签: haskell pattern-matching

我想创建一个数据类型,它可以采用长度为2或3的元组,并且应该包含派生Num和Ord的类型。然后,我想在我的类型类实例中对这个元组的长度进行模式匹配,以便我可以根据元组长度决定使用哪个函数。看看下面的不可编译的伪代码。至少有两个问题:

  1.   

    Dominates不是可导出的类

  2. 我不知道如何获取元组,例如调用fitnesses,以便在实例中的模式匹配时从数据类型中获取变量。

  3. 代码:

    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;的实例。

1 个答案:

答案 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