2

I have written a function to get a pair from [-10,10] by random.

import System.Random


main = 
    do { 
         s <- randomNumber
       ; b <- randomNumber
       ; print (head s,head b)}
randomNumber :: IO [Int]
randomNumber = sequence $ replicate 1 $ randomRIO (-10,10)

Now I want to take a list like [(1,2),(2,3),(2,3)], all the number is come from the randomNumber. How can I do that? I don't know how to achieve that.

I have tried to use state to get random, but somehow I can't use state on my computer. I did this :

import System.Random
import Control.Monad.State
randomSt :: (RandomGen g, Random a) => State g a
randomSt = State random

But when I compiled it, it showed: Not in scope: data constructor ‘State’

1 Answer 1

5

So if all you want is a function

  randomPairs :: IO [(Int, Int)]

then we can do something like

   randomList :: IO [Int]
   randomList = randomRs (-10, 10) `fmap` newStdGen
   randomPairs = ??? randomList randomList

where ??? takes two IO [Int] and "zips" them together to form a IO [(Int, Int)]. We now turn to hoogle and query for a function [a] -> [a] -> [(a, a]) and we find a function zip :: [a] -> [b] -> [(a, b)] we now just need to "lift" zip into the IO monad to work with it across IO lists so we end up with

  randomPairs = liftM2 zip randomList randomList

or if we want to be really fancy, we could use applicatives instead and end up with

  import Control.Applicative

  randomPairs = zip <$> randomList <*> randomList

But judging from your randomNumber funciton, you really just want one pair. The idea is quite similar. Instead of generating a list, we generate just one random number with randomRIO (-10, 10) and lift (,) :: a -> b -> (a, b) resulting in

  randomPair = (,) <$> randomRIO (-10, 10) <*> randomRIO (-10, 10)

Finally, the State data constructor went away a while ago because the MTL moved from having separate State and StateT types to making State a type synonym. Nowadays you need to use the lowercase state :: (s -> (s, a)) -> State s a

To clarify, my final code is

import System.Random
import Control.Monad

randomList :: IO [Int]
randomList = randomRs (-10, 10) `fmap` newStdGen

pairs :: IO [(Int, Int)]
pairs = liftM2 zip randomList randomList

somePairs n = take n `fmap` pairs

main = somePairs 10 >>= print
Sign up to request clarification or add additional context in comments.

7 Comments

As you can see, I have imported Control.Monad.State, then I still can't use it.
Hi, your code passed the compile, but when I run it, it shows out of memory. Looks like there is something wrong of the randomList?
@Xie Indeed, I've updated to take advantage of newStdGen and randomRs, how that works should be pretty clear from the types
Hi, this new code actually get the same number for every pair. I change your last code to randomList = sequence . replicate 1$ randomRIO (-10, 10) randomPairs = zip <$> randomList <*> randomLis , it get a great pair. Actually, I would like to get n pairs for [-10,10], and the n is under control. How could I achieve that?
Like take n randomPairs, but looks like the type is error
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.