Here's a hacky solution with some extra tweaking, but no backlinks! I first posted this on reddit if everything is ok.
I assume you got Enum for Rank .
data OF = OF ace :: OF -> Suit -> PokerCard ace _ s = PokerCard Ace s -- or point-free two :: OF -> Suit -> PokerCard two _ = PokerCard Two -- or with const three :: OF -> Suit -> PokerCard three = const (PokerCard Three) -- you get the idea! -- the rest in one line: four,five,six,seven,eight,nine,ten,jack,king :: OF -> Suit -> PokerCard [four,five,six,seven,eight,nine,ten,jack,king] = map (const . PokerCard) [Four .. King] -- now you can write pokerDeck = [ ace OF Spades, two OF Spades -- and so on ]
The OF data type is not strictly necessary, but it prevents obfuscation of the (but very metallic) material, such as ace "Motorhead" Spades . You can still write ace undefined Spades , in my opinion there is no way around it.
If of not a keyword, you could even write of = OF .
There is also a completely evil hack to completely get rid of "of" and use card numbers:
{-# LANGUAGE FlexibleInstances #-} -- this goes on top of your file instance Num (Rank -> Suit) where fromInteger n = (undefined : map Card[Ace .. King]) !! (fromInteger n)
Now there are 2 Spades :: Card typechecks (but you need an explicit type!) And this is what you think :-) However, I strongly recommend that you do not do this in serious code; but it looks cool.