Reputation: 865
First of this is homework so please don't give to much away! I need to understand this and not copy someone else's code.
I have to create a deck of cards. And I have been given code to use and I just can't get them to work. I mean I can create the deck of cards best in show 2012-2013 but that does not help me at all as I need to use the code we are given and I'm not allowed to change it.
(I use Read and Enum to create a deck of cards and that one looks stunning, but I can't for this assignment)
I get a few error msg in the end which you can see.
import Test.QuickCheck
--DECK OF CARDS
data Suit = Hearts | Spades | Diamonds | Clubs
deriving (Eq, Show)
data Card = Card Rank Suit
deriving (Eq, Show)
data Rank = Numeric Integer | Jack | Queen | King | Ace
deriving (Eq, Show)
instance Arbitrary Rank where
arbitrary = frequency [ (1, return Jack)
, (1, return Queen)
, (1, return King)
, (1, return Ace)
, (9, do n <- choose (2, 10)
return (Numeric n))
]
--MY OWN CODE
type Deck = [Card]
deck :: Deck
deck = [Card v s | v <- arbitrary Rank, s <- Suit]
When I try to load it I get:
Prelude> :l test4
[1 of 1] Compiling Main ( test4.hs, interpreted )
test4.hs:31:35: Not in scope: data constructor `Rank'
test4.hs:31:46: Not in scope: data constructor `Suit'
Failed, modules loaded: none.
Where am I going wrong? Am I missing something fundamental? If so where do I read up on it?
I will be grateful for any and all suggestions and ideas!
Upvotes: 3
Views: 591
Reputation: 26097
It looks like you do have a basic misunderstanding: in your list comprehension, you are trying to use Rank
and Suit
like lists, but they aren't -- they're type names. If you want to iterate over a list of suits, you need to make one yourself.
In expressions, a capitalized identifier is expected to be a data constructor (because types don't make any sense in that context). The compiler error is not especially helpful here -- it is looking up Rank
and Suit
in the data constructor namespace, and not finding them.
Upvotes: 2
Reputation: 11208
I would point out several problems with your code:
The type of arbitrary
is arbitrary :: Arbitrary a => Gen a
. So you need something to run this generator to get the random list.
Rank
and Suit
are types and not some value. Also you need to explicitly give type to arbitrary
to get that type of generator. like arbitrary :: (Gen Rank)
and then run with
something like sample'
or some other function to actually get the random Ranks.
Similarly you need to define instance of arbitrary for Card
, Suit
and Deck
. Then you can generate a Deck
by just typecasting arbitrary
to Gen Deck
More of a logical flaw. Your arbitrary instance will not guarantee constraints like there should be exactly 4 kings etc in a deck. So while defining an arbitrary instance for Deck
you should take care of that.
Refer to the types of function in Test.QuickCheck
while defining arbitrary
instances. You will get most of the things right by just looking at the types.
Upvotes: 3