Haskell method for listing

So. I want to introduce a type like this:

(Card, Suit)

represent cards in a card game, where the Cardcopies will be in the set:

{2, 3, 4, 5, 6, 7, 8, 9, J, Q, K, 1}

and Suitwill have instances in the set:

{S, D, H, C}

I would handle this with two Data declarations if it weren’t for numbers:

data Suit = S | D | H | C deri...

but, obviously, adding numbers to these types of empty arity will fail.

So my question is how to simulate the type of enum you find in C?

I assume that I am carrying the principle point of the type system and the help will be appreciated!

EDIT: I will add some context: I want to present the data contained in this Euler problem , as you can check, the data is presented as 1S for ace of spade, 2D for 2 diamonds, etc.

, .

+3
3

, -. , .

-, . - , ( Show)

import Text.ParserCombinators.Parsec

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

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

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

instance Show Card where
    show (Card rank suit) = show rank ++ " of " ++ show suit

, Parsec. , ..

, , , (, , ) , . : (, Ace Two), , Two 0, Three 1 ..

parseRank ( ). : (a) , (b) , , (c) , , .

parseSuit :: Parser Suit
parseSuit = do s <- oneOf "SDCH"
               return $ case s of
                'S' -> Spades
                'D' -> Diamonds
                'H' -> Hearts
                'C' -> Clubs

parseRank :: Parser Rank
parseRank = do r <- oneOf "23456789TJQKA"
               return $ case r of
                'T' -> Ten
                'J' -> Jack
                'Q' -> Queen
                'K' -> King
                'A' -> Ace
                 n  -> toEnum (read [n] - 2)

parseCard :: Parser Card
parseCard = do r <- parseRank
               s <- parseSuit
               return $ Card { rank = r, suit = s }

readCard :: String -> Either ParseError Card
readCard str = parse parseCard "" str

:

*Cards> readCard "2C"
Right Two of Clubs
*Cards> readCard "JH"
Right Jack of Hearts
*Cards> readCard "AS"
Right Ace of Spades

Edit:

@yatima2975 , OverloadedStrings. , . , {-# LANGUAGE OverloadedStrings #-} import GHC.Exts ( IsString(..) ), . Card :

instance IsString Card where
    fromString str = case readCard str of Right c -> c

, , :

isAce :: Card -> Bool
isAce "AH" = True
isAce "AC" = True
isAce "AD" = True
isAce "AS" = True
isAce _    = False

:

printAces = do
    let cards = ["2H", "JH", "AH"]
    mapM_ (\x -> putStrLn $ show x ++ ": " ++ show (isAce x)) cards

:

*Cards> printAces
Two of Hearts: False
Jack of Hearts: False
Ace of Hearts: True
+17
data Card = Two | Three | Four | Five | Six
          | Seven | Eight | Nine | Ten
          | Jack | Queen | King | Ace
    deriving Enum

Enum typeclass , fromEnum toEnum Card Int.

, , fromEnum Two 2, Enum Card . ( 0, C, , .)

n.b. Enum --- , , , < ==, Card s, deriving Ord.


Edit:

read, String "2S" "QH" (Card, Suit), read , "(a,b)" (, "(2,S)" , , "(Two,S)" ).

. (, Parsec Attoparsec), .

.

{-# LANGUAGE TupleSections #-}

parseSuit :: String -> Maybe Suit
parseSuit "S" = Just S
...
parseSuit _   = Nothing

parseCard :: String -> Maybe (Card, Suit)
parseCard ('2' : s) = fmap (Two,) (parseSuit s)
...
parseCard _         = Nothing
+8

Id just prefix the numbers with a letter or, better yet, a word. Id also doesn't use too many single-letter abbreviations - H, Ketc. Completely unreadable.

data Suit = Club | Spade | Heart | Diamond
data Card = Card1 | Card2 | … | Jack | Queen | King | Ace

... But I even prefer to suggest words to use numeric words ( One, Two) instead of meanings.

+1
source

All Articles