2

一张卡片有一个类型和一个颜色:

data CardType = Spades | Clubs | Diamonds | Hearts

data CardColor = Black | Red

cardColor :: CardType -> CardColor

cardColor card =
  case card of Spades -> Black
               Clubs -> Black
               Diamonds -> Red
               Hearts -> Red

type Card = (CardType, CardColor)

我想检查所有卡片是否具有相同的颜色:

allTheSameColor :: [Card] -> Bool

allTheSameColor cardList = ???

我想知道,如果使用任何库函数,我将如何做到这一点filter?但是它允许自己重新实现它,因为我希望能够在更深的功能层面上理解如何解决这个问题。

4

2 回答 2

4

CardColor应派生于Eq可比较的:

data CardColor = Black | Red
                         deriving (Eq)



allTheSameColor :: [Card] -> Bool
allTheSameColor [] = True
allTheSameColor [x] = True
allTheSameColor (x:y:xs) = if (snd x) == (snd y) then allTheSameColor (y:xs)
                           else False          

更准确地说,您如何说列表中的数字相同?不要想你需要什么步骤或过程来计算,考虑列表元素之间的关系,你需要弄清楚列表元素是否相同。这种关系原来是这样的:第一个元素==第二个元素和第二个元素==第三个元素,依此类推,直到列表的长度。

于 2013-10-27T12:04:36.280 回答
3

我的额外列表函数模块中的一个函数是allSameBy. 像这样

allSameBy :: (a -> a -> Bool) -> [a] -> Bool
allSameBy _ [] = True
allSameBy eq (x:xs) = all (eq x) xs

您的问题可以通过以下方式轻松解决

allTheSameColor = allSameBy ((==) `on` snd)

或者(效率较低),您可以定义allSameBy

allSameBy eq xs = length (groupBy eq xs) <= 1

编辑:或者如果您不想使用任何库函数(并且语义略有不同)

allSameBy _ [] = True
allSameBy _ [_] = True
allSameBy eq (x:xs@(y:_)) = case eq x y of False -> False; True -> allSameBy eq xs
于 2013-10-27T12:49:43.623 回答