
Hi All, From: http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State Exercises 1. Implement a function rollNDiceIO :: Int -> IO [Int] that, given an integer, returns a list with that number of pseudo- random integers between 1 and 6. After a lot of learning what not to do, this is the best I could come up with. rollNDiceIO :: Int -> IO [Int] rollNDiceIO n = mapM (\x -> randomRIO(1,6)) (replicate n 1) I know, ugly, but at least I got it to work. What's a better way to generate this list? Michael

On Sun, Jul 25, 2010 at 5:39 PM, michael rice
I know, ugly, but at least I got it to work. What's a better way to generate this list?
rollNDiceIO n = sequence . replicate n $ randomRIO (1,6) {{ sequence . replicate n = replicateM n }} = replicateM n $ randomRIO (1, 6) --Max

Hi Max,
Wow!
I tried both *sequence* and *replicate* but guess I didn't put them together properly. I didn't even know there was a *replicateM*.
Much cleaner.
Thanks
Michael
--- On Sun, 7/25/10, Max Rabkin
I know, ugly, but at least I got it to work. What's a better way to generate this list?
rollNDiceIO n = sequence . replicate n $ randomRIO (1,6) {{ sequence . replicate n = replicateM n }} = replicateM n $ randomRIO (1, 6) --Max

Sorry but I'll just go ahead and eta reduce it :)
rollNDiceIO = flip replicateM $ randomRIO (1,6)
On 25 July 2010 16:44, Max Rabkin
On Sun, Jul 25, 2010 at 5:39 PM, michael rice
wrote: I know, ugly, but at least I got it to work. What's a better way to
generate this list?
rollNDiceIO n = sequence . replicate n $ randomRIO (1,6) {{ sequence . replicate n = replicateM n }} = replicateM n $ randomRIO (1, 6)
--Max _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Ozgur Akgun

Cool. Everything's there but the N.
Learning Haskell is a lot like learning to dance.
Michael
--- On Sun, 7/25/10, Ozgur Akgun
I know, ugly, but at least I got it to work. What's a better way to generate this list?
rollNDiceIO n = sequence . replicate n $ randomRIO (1,6) {{ sequence . replicate n = replicateM n }} = replicateM n $ randomRIO (1, 6) --Max _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ozgur Akgun

I find it useful to have a seed argument to nearly all random functions rather than using ones with an IO signature. This way you can speed up your program quite a bit and also make testing much easier. I think that MonadRandom does this automatically too.

Hi Lyndon,
Since the example immediately above the exercise used randomRIO, I assumed that randomRIO was to be used as part of the solution to the exercise.
http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State
Also, it was the above mentioned example that introduced me to *liftM2*, about which I posted a question a couple of days ago (subject line: Heavy lift-ing).
The next topic on the wiki page is "Getting Rid of the IO" which seems to be the direction of your post. No doubt I'll have more questions as I plod on.
Thanks for your input,
Michael
--- On Mon, 7/26/10, Lyndon Maydwell

Look for the function replicateM in the module Control.Monad.
On 25 July 2010 17:39, michael rice
Hi All,
From: http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State
Exercises
1. Implement a function rollNDiceIO :: Int -> IO [Int] that, given an integer, returns a list with that number of pseudo- random integers between 1 and 6.
After a lot of learning what not to do, this is the best I could come up with.
rollNDiceIO :: Int -> IO [Int] rollNDiceIO n = mapM (\x -> randomRIO(1,6)) (replicate n 1)
I know, ugly, but at least I got it to work. What's a better way to generate this list?
Michael
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Sun, Jul 25, 2010 at 11:39 AM, michael rice
Hi All,
From: http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State
Exercises
1. Implement a function rollNDiceIO :: Int -> IO [Int] that, given an integer, returns a list with that number of pseudo- random integers between 1 and 6.
After a lot of learning what not to do, this is the best I could come up with.
rollNDiceIO :: Int -> IO [Int] rollNDiceIO n = mapM (\x -> randomRIO(1,6)) (replicate n 1)
I know, ugly, but at least I got it to work. What's a better way to generate this list?
An even better method lets the list be generated lazily. import Data.Functor ((<$>)) import Random rollDice :: IO [Int] rollDice = randomRs (1,6) <$> newStdGen rollNDice :: Int -> IO [Int] rollNDice n = take n <$> rollDice This is important because randomRIO has to peek at an MVar to determine the current value of the random number seed _for each die rolled_, but using randomRs on a fresh StdGen only has does so once. Moreover, it gives you the more general 'rollDice' funtion, which can give you an infinite list of random dice rolls. Trying to implement that function using the approach you used will lead to a computation that won't terminate. -Edward Kmett
participants (6)
-
Edward Kmett
-
Lyndon Maydwell
-
Max Rabkin
-
michael rice
-
Ozgur Akgun
-
Tobias Brandt