使用列表推导在Haskell中使用完整甲板

时间:2018-09-19 18:14:19

标签: haskell

我对Haskell(和编程)很陌生。 我的任务是定义一个函数,该函数返回一整张纸牌(也称为52张纸牌)。试图在代码旁边的注释中包括我的思考过程。

-我定义的值

data Suit = Club | Diamond | Heart | Spade  deriving (Show, Enum)

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

type Card = (Suit, Value)  -- A card must have a suit and a value
type Deck = [Card]        -- A deck consists of a list of cards

fullDeck :: Deck    -- My function is supposed to consist of a deck
fullDeck = [(suit, value) | suit <- [Club..Spade], value <- [Two..Ace]]  -- Tried my luck using ''list comprehensions''. Is it necessary to type [Club..Spade] or does it work for just [Club..] as well? 

我的代码无法加载。我收到的错误:

beginner.hs:11:62: error:
    A section must be enclosed in parentheses thus: (Two.. Ace)
   |
11 | fullDeck = [(suit, value) | suit <- [Club..Spade], value <- [Two..Ace]]

无论我如何尝试解决此问题,都会出现一些新错误,因此我显然在做一些我无法找到的重大故障。

我也很好奇如何确保卡组中只有52张卡片,因为目前我的列表中包含无限数量的卡片?

1 个答案:

答案 0 :(得分:6)

您忘记了在数据构造函数(例如ClubSpade)和..运算符之间使用空格。如果不这样做,Haskell会将其视为点,例如用于限定导入。

以下作品:

[(suit, value) | suit <- [Club .. Spade], value <- [Two .. Ace]]
--                            ^  ^                     ^  ^

这会产生预期的结果:

Prelude> [(suit, value) | suit <- [Club .. Spade], value <- [Two .. Ace]]
[(Club,Two),(Club,Three),(Club,Four),(Club,Five),(Club,Six),(Club,Seven),(Club,Eight),(Club,Nine),(Club,Ten),(Club,Jack),(Club,Queen),(Club,King),(Club,Ace),(Diamond,Two),(Diamond,Three),(Diamond,Four),(Diamond,Five),(Diamond,Six),(Diamond,Seven),(Diamond,Eight),(Diamond,Nine),(Diamond,Ten),(Diamond,Jack),(Diamond,Queen),(Diamond,King),(Diamond,Ace),(Heart,Two),(Heart,Three),(Heart,Four),(Heart,Five),(Heart,Six),(Heart,Seven),(Heart,Eight),(Heart,Nine),(Heart,Ten),(Heart,Jack),(Heart,Queen),(Heart,King),(Heart,Ace),(Spade,Two),(Spade,Three),(Spade,Four),(Spade,Five),(Spade,Six),(Spade,Seven),(Spade,Eight),(Spade,Nine),(Spade,Ten),(Spade,Jack),(Spade,Queen),(Spade,King),(Spade,Ace)]

我们也可以像@Amalloy所说的那样,设置类型Bounded,然后将其写为:

data Suit = Club | Diamond | Heart | Spade  deriving (Show, Enum, Bounded)

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

fullDeck :: Deck    -- My function is supposed to consist of a deck
fullDeck = [(suit, value) | suit <- [minBound ..], value <- [minBound ..]]

或者我们可以定义一个辅助值:

boundedAll :: (Bounded a, Ord a) => [a]
boundedAll = [minBound ..]

然后将其写为:

fullDeck :: Deck
fullDeck = (,) <$> boundedAll <*> boundedAll