user1501127
user1501127

Reputation: 865

Data types and Arbitrary, add them together?

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

Answers (2)

comingstorm
comingstorm

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

Satvik
Satvik

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

Related Questions