哈斯克尔:制作一副纸牌

Sha*_*abu 2 haskell list

我是Haskell的新手,并且在使用递归制作一副牌时遇到了问题.

我有这些定义:

data Suit = Club | Diamond | Heart | Spade

data Value = Two | Three | Four | Five | Six | Seven
              | Eight | Nine | Ten | Jack | Queen
              | King | Ace

type Card = (Suit, Value)
type Deck = [Card]

instance Show Suit where
   show Club = "Club"
   show Diamond = "Diamond"
   show Heart = "Heart"
   show Spade = "Spade"

instance Show Value where
  show Two = "Two"
  show Three = "Three"
  show Four = "Four"
  show Five = "Five"
  show Six = "Six"
  show Seven = "Seven"
  show Eight = "Eight"
  show Nine = "Nine"
  show Ten = "Ten"
  show Jack = "Jack"
  show Queen = "Queen"
  show King = "King"
  show Ace = "Ace"
Run Code Online (Sandbox Code Playgroud)

我正在尝试编写一个函数

makeDeck :: Deck
Run Code Online (Sandbox Code Playgroud)

它按照给出数据的顺序返回一张牌列表,所以(Club,Two - Ace),(Diamond,Two-Ace)等等.

我想用递归来做这个,这就是我遇到这么多困难的原因.

任何帮助将不胜感激.

谢谢!

iva*_*anm 10

这不使用递归,但更常规的方法是:

添加deriving Enum到Suit和Value的定义,然后:

makeDeck :: Deck
makeDeck = [(suit, value) | suit <- [Club..Spade], value <- [Two..Ace]]
Run Code Online (Sandbox Code Playgroud)

或者,提供所有套装和值的完全定义的列表,而不是使用Enum.

  • 或者使用`Applicative`s,`makeDeck =(,)<$> [Club ..] <*> [Two ..] (7认同)
  • @newacct:这也需要一个`Bounded`实例,也可以派生. (2认同)

Mat*_*ick 6

鉴于:

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)
type Deck = [Card]

makeDeck :: Deck
Run Code Online (Sandbox Code Playgroud)

有很多方法可以计算笛卡尔积——集合的积。这些示例中使用的所有函数都可以在 Hoogle 上查找:

单子

使用 do 符号:

makeDeck = do
    suit <- [Club ..]
    value <- [Two ..]
    return (suit, value)
Run Code Online (Sandbox Code Playgroud)

上面的无糖形式,它使用>>=

makeDeck = [Club ..] >>= \suit ->
    [Two ..] >>= \value ->
    return (suit, value)
Run Code Online (Sandbox Code Playgroud)

起重:

makeDeck = liftM2 (,) [Club ..] [Two ..]
Run Code Online (Sandbox Code Playgroud)

monad 中的函数应用:

makeDeck = return (,) `ap` [Club ..] `ap` [Two ..]
Run Code Online (Sandbox Code Playgroud)

应用程序

起重:

makeDeck = liftA2 (,) [Club ..] [Two ..]
Run Code Online (Sandbox Code Playgroud)

applicatives 内的函数应用:

makeDeck = pure (,) <*> [Club ..] <*> [Two ..]
Run Code Online (Sandbox Code Playgroud)

这与以下内容相同:

makeDeck = (,) <$> [Club ..] <*> [Two ..]
Run Code Online (Sandbox Code Playgroud)

列表推导式

请参阅@ivanm 的答案。

没有任何类型类

makeDeck = concatMap (\suit -> map ((,) suit) [Two ..]) [Club ..]
Run Code Online (Sandbox Code Playgroud)

如果您需要显式使用递归,您可以替换concatMap为它的定义,依此类推,直到到达foldr真正的递归操作发生的地方。