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

CardColorEq比較できるようにするには、次から派生する必要があります。

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          

より正確に言えば、リスト内の数字が同じであるとどのように言えますか? それを理解するために必要なステップや手順を考えるのではなく、リストの要素が同じかどうかを調べるために把握する必要があるリストの要素間の関係の観点から考えてください。その関係は次のようになります。最初の要素 == 2 番目の要素 AND 2 番目の要素 == 3 番目の要素というように、リストの長さまで続きます。

于 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 に答える