6

私は Haskell を学んでいるので、簡単なカード ゲームを書いています。いくつかのデータ型を定義しました:

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

data Suit = Hearts|Spades|Diamonds|Clubs deriving (Show)

data Card = Card Rank Suit 

ここで、52 枚のカードからなる純粋なデッキを作成したいと思います。それを行うための巧妙な方法があると確信していますが、私が思いつくことができるのは次のとおりです。

 pristineDeck = [Card Ace Hearts, Card Two Hearts, ...]

Haskell にこのリストを生成してもらうことはできますか?

4

3 に答える 3

9

リスト内包表記は、このための非常にきちんとした構文です。Enum派生した場合Rank、次のSuitように非常に簡単に表現できます。

pristineDeck = [ Card rank suit | suit <- [Hearts .. Clubs], rank <- [Ace .. King] ]

なぜ私が異なる順序でsuitとを持っているのか疑問に思っているなら、最初の理由はコンストラクターが使用する順序のためであり、後者は結果のリストの順序を取得するためです-昇順で一緒にスーツ.rankCard

より一般的に、または単一のリスト内包表記が大きくなりすぎる場合、デカルト積はまさにMonadリストのインスタンスによって与えられる動作です。以下は、上記のリスト内包表記と同等です。

pristineDeck = do suit <- [Hearts .. Clubs]
                  rank <- [Ace .. King]
                  return $ Card rank suit

もう 1 つのマイナーな点として、値の順序を覚える手間を省くためSuitに、派生によって、 と の両方のインスタンスを持つ任意の型のすべての値を列挙Boundedするように記述できるようになります。[minBound .. maxBound]EnumBounded

于 2013-01-04T23:48:42.217 に答える
7

これを行うにはいくつかの方法があり、さまざまな量の魔法があります。

まず、型のコンストラクターには引数がないEnumため、それらを派生させることができます。[Ace..King]これにより、すべてのカードのリストを取得するなどの書き込みが可能になります。

第二に、リスト内包表記は、他の複数のリストから引き出された項目のリストを形成する優れた方法です。これを試して:

[x + y | x <- [100,200,300], y <- [1,2,3]]

これにより、例に適用するために必要なツールが提供されます。

于 2013-01-04T23:49:13.897 に答える
3

列挙型を導出するように指示する上でAlpは正しい

>data Rank = Ace|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|Jack|Queen|King deriving (Eq,Show,Ord,Enum)
>data Suit = Hearts|Spades|Diamonds|Clubs deriving (Show,Enum)

今:

>enumFrom Ace
[Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King]

2つのリストの順列を取得するには、リスト内包表記を使用できます。

>[[x,y]|x<-[1..2],y<-[2..5]]
[[1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5]]

または加算の順列を取得するには:

>[x + y|x<-[1..2],y<-[2..5]]
[3,4,5,6,4,5,6,7]

ここで、ランクとスーツのある車の順列を取得するために、いくつかの置換を行う必要があります。

于 2013-01-04T23:58:08.473 に答える