简体   繁体   中英

Generating random values in Haskell

I am using the Real World Haskell book. The statement

ghci> import Test.QuickCheck
ghci> generate 10 (System.Random.mkStdGen 2) arbitrary :: [Bool]

results in

<interactive>:8:1: error:
* Couldn't match expected type `StdGen -> Gen a1 -> [Bool]'
              with actual type `IO a0'
* The function `generate' is applied to three arguments,
  but its type `Gen a0 -> IO a0' has only one
  In the expression: generate 10 (mkStdGen 2) arbitrary :: [Bool]
  In an equation for `it':
      it = generate 10 (mkStdGen 2) arbitrary :: [Bool]

If I am reading the error correctly it seems that "System.Random.mkStdGen 2" is now generating a monad? How do I get this statement to work?

Edit: Added import statement to clarify

One key part of the error message you got is here:

* The function `generate' is applied to three arguments,
  but its type `Gen a0 -> IO a0' has only one

This is saying that generate should only take one element, but you've given it three. Specifically, you've given it 10 , System.Random.mkStdGen 2 , and arbitrary . Just by looking at the types, it seems clear that your best bet to get a working program is to just drop the first two arguments to get:

generate arbitrary :: IO [Bool]

But, I'm guessing you had a reason for putting 10 and mkStdGen 2 in, yes? Perhaps you wanted to produce 10 Bool s (or 10 [Bool] ?) and to use your own custom seed? You can't just throw more arguments at a function to get it to do what you want, but if you follow the types, you'll get there.

First, there's using a custom seed. To do this, we'll need to abandon generate and make our own generateWithSeed :

import Test.QuickCheck.Random (mkQCGen)

-- | Run a generator. The size passed to the generator is always 30;
-- if you want another size then you should explicitly use 'resize'.
generateWithSeed :: Int -> Gen a -> IO a
generateWithSeed seed (MkGen g) =
  do r <- mkQCGen seed
     return (g r 30)

Getting multiple results is actually easier -- we can use replicateM :

import Control.Monad (replicateM)

generateMultipleWithSeed :: Int -> Int -> Gen a -> IO [a]
generateMultipleWithSeed n seed g = generateWithSeed seed (replicateM n g)

Now you can run your original line (although with a slightly different type annotation):

generateMultipleWithSeed 10 2 (arbitrary :: Gen Bool)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM