2013-01-04 24 views
5

Tôi đang học Haskell, vì vậy tôi đang viết một số trò chơi bài giản dị. Tôi đã xác định một số loại dữ liệu:Haskell: Cách tạo ra một sản phẩm Descartes của hai loại dữ liệu đại số đơn giản

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 

Bây giờ tôi muốn tạo một bộ bài nguyên sơ gồm 52 thẻ. Tôi chắc chắn có một cách khéo léo để làm điều đó, nhưng tất cả những gì tôi có thể đưa ra là:

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

Tôi có thể lấy Haskell để tạo danh sách này cho tôi không?

+2

Làm cho các loại của bạn lấy được chữ "Enum" (có thể xảy ra bằng cách đặt Enum cạnh 'Hiển thị' ở trên đó). Ba người trong số họ: Rank, Suit và Card. –

+1

P.S. những gì bạn đang tìm kiếm không phải là sản phẩm chéo, mà là một cái gì đó liên quan đến vectơ 3D. Bạn có thể có nghĩa là "sản phẩm Descartes". –

+0

@BenMillwood My bad ... "SQL tham gia chéo" + "sản phẩm Descartes" + độ trong vật lý –

Trả lời

10

Việc hiểu danh sách là một cú pháp rất gọn gàng cho việc này. Nếu bạn lấy được Enum trên RankSuit bạn có thể thể hiện nó rất đơn giản như:

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

Nếu bạn đang tự hỏi tại sao tôi có suitrank thứ tự khác nhau, đầu tiên là vì thứ tự các nhà xây dựng Card sử dụng, trong khi thứ hai là để có được thứ tự của danh sách kết quả - phù hợp với nhau theo thứ tự tăng dần.

Trong tính tổng quát hơn, hoặc khi một danh sách duy nhất hiểu được quá cồng kềnh, sản phẩm Descartes chính xác là hành vi được đưa ra bởi ví dụ Monad cho danh sách. Sau đây là tương đương với hiểu danh sách trên:

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

Là một trong những điểm nhỏ khác, để tiết kiệm cho mình những rắc rối của ghi nhớ những gì ra lệnh cho Suit giá trị trong, bắt nguồn Bounded cũng sẽ cho phép để viết [minBound .. maxBound] để liệt kê tất cả giá trị của bất kỳ loại nào với các phiên bản của cả hai số EnumBounded.

+1

Cá nhân tôi sẽ không lấy được 'Enum' cho loại' Suit', và chỉ viết ra toàn bộ danh sách trong phần hiểu. Bộ quần áo không có thứ tự tự nhiên, IMO, do đó cú pháp hình elip là khó hiểu. –

+2

Và tôi cũng sẽ lấy được một trường hợp 'Bounded'. '[minBound .. maxBound]' làm cho nó rõ ràng rằng bạn đang liệt kê tất cả các biến thể, ngay cả khi không có thứ tự tự nhiên. –

+0

@ C.A. McCann Hãy cẩn thận để gõ '[Hearts .. Clubs]' và '[Ace .. King]', nếu không bạn sẽ nhận được một lỗi: 'Không nằm trong phạm vi: 'Hearts ..''. –

7

Có một số cách để thực hiện việc này, với số lượng thuật sĩ khác nhau.

Thứ nhất, vì không có nhà thầu nào trong số các loại của bạn có đối số, bạn có thể lấy được Enum cho họ. Điều này sẽ cho phép bạn viết ví dụ: [Ace..King] để nhận danh sách tất cả các thẻ.

Thứ hai, việc hiểu danh sách là một cách tuyệt vời để tạo danh sách các mục được vẽ từ nhiều danh sách khác. Hãy thử điều này:

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

Điều đó sẽ cung cấp cho bạn các công cụ bạn cần để áp dụng cho ví dụ của bạn.

3

Alp là đúng trên cho bạn biết để lấy được Enum

>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) 

Bây giờ là:

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

Để có được hoán vị của hai danh sách, bạn có thể sử dụng danh sách hiểu:

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

hoặc để có được các hoán vị bổ sung:

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

Bây giờ bạn chỉ cần thực hiện một vài thay thế để có được hoán vị của Ô tô có Xếp hạng và Phù hợp.

Các vấn đề liên quan