haskell 构造这种数据类型的更惯用的方法是什么?

wgx48brx  于 2022-11-30  发布在  其他
关注(0)|答案(2)|浏览(177)

我在Haskell中创建了一个纸牌游戏,我需要知道每种花色的纸牌颜色。
现在,我使用cardCombinations构造花色、排名和颜色的所有可能组合,然后使用cardWithColors过滤结果以构造Deck
要求是我希望套装具有正确的关联颜色:方块红桃和黑桃梅花是黑色的。
有没有可能有一种更简洁的方式来表达这种逻辑,而不是先构造所有组合,然后再过滤它们?

module Deck (Suit,Color,Rank,Card,Deck) where

data Color = Red | Black deriving (Eq,Enum,Show,Ord,Bounded)

data Suit = Clubs | Diamonds | Hearts | Spades deriving (Eq,Ord,Enum,Bounded,Show)

data Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
          | Jack | Queen | King | Ace deriving (Eq,Ord,Enum,Bounded,Show)  

data Card = Card { rank :: Rank
                 , suit :: Suit
                 , color :: Color } deriving (Eq,Ord,Bounded,Show)

type Deck = [Card]

findColorForSuit :: Suit -> Color 
findColorForSuit suit 
    | any (suit==) [Diamonds, Hearts] = Red
    | any (suit==) [Spades, Clubs] = Black

cardCombinations = [(ranks, suits, colors) | ranks <- [minBound :: Rank .. maxBound :: Rank], suits <- [minBound :: Suit .. maxBound :: Suit], colors <- [minBound :: Color .. maxBound :: Color]]

cardsWithColors = filter (\(_,suit,color) -> (findColorForSuit suit) == color) cardCombinations

makeCard :: (Rank, Suit, Color) -> Card 
makeCard (rank, suit, color) = Card rank suit color 

makeCards :: Deck
makeCards = map makeCard cardsWithColors

我试着创建所有组合,然后根据过滤器 predicate 过滤结果,以确定如何将颜色与套装相关联。

yks3o0rb

yks3o0rb1#

这些要求也被称为不变量,习惯上的做法是尽可能避免它们(使非法状态不可表示)。有时避免所有不变量确实很难和/或不实际,然而,在您的情况下,这真的很容易,因为每张卡的ColorSuit唯一确定。除了color字段,您可以将其定义为函数。

data Card = Card { rank :: Rank, suit :: Suit }
  deriving (..)

color :: Card -> Color
color card = findColorForSuit (suit card)

这意味着每一张Card都是一张有效的牌,你可以构造所有可能的行列和花色组合。

enxuqcxy

enxuqcxy2#

我会让Card只包含排名和花色,然后编写一个函数来 * 计算 * 颜色(通过使用findColourForSuit,尽管如果使用单个模式匹配,而不是使用any==和列表,这会更简单)。
你不需要存储每一张牌的颜色,它是由你已经存储的花色所暗示的,就像我们不需要在每一张Integer上放置一个字段even :: Bool;我们只存储整数的值,当我们需要知道它是奇数还是偶数时,我们计算它。

相关问题