Take the 2-minute tour ×

I am with trouble related to Haskell Random generator. At university, i have to deal with Java all my way around, so now I'm, corrupted with it. I am developing a game in Haskell, and now I face something like 'chance to do something', and that chance needs to be like Int -> Bool. In Java, I would have done

new Random().nextInt(100) 

and there, problem solved! In Haskell I have to choose something in a monad IO or something with a seed. None of these does what I want. I don't really want to use IO monad in my pure model, and the seed is awkward to use because I need to remember my new seed every time...

Is there something simple like Java's Random?

share|improve this question
Using the IO Monad does not mean that you have to corrupt with IO your whole model... Just get your seed right at the beginning, and give it to your pure computations... Your program will be of type IO () remember ? So you're already in the IO Monad... (if your game is 100% pure, then it must not be really fun to play!) –  Ptival Sep 7 '11 at 6:17
You'll 'corrupt' your self soon or later, a game need I/O from player :D –  Zhen Sep 7 '11 at 7:25
The top-rated answer on this question: http://stackoverflow.com/questions/2110535/sampling-sequences-of-random-numbers‌​-in-haskell gives an excellent write-up of how to thread a stateful random number generator through code. –  stusmith Sep 7 '11 at 10:57
"I don't really want to use IO monad in my pure model". In Java, new Random() is far from pure. And every time you use nextInt, your Random object mutates. So your goals of 1) a pure model, and 2) something like Java's Random, are in conflict since Java's Random is not pure. –  Dan Burton Sep 7 '11 at 14:54
java is soo far from pure model as i see it :P, i meant that. but indeed, I was focused the wrong head, my head is already corrupt! thanks for andswers and comments everybody! –  Illiax Sep 7 '11 at 16:20
add comment

4 Answers

It is somewhat unintuitive that something that neither does input nor output needs to be handled as if it had. Let's say you defined it as follows:

random100 = unsafePerformIO $ randomRIO (1, 100) -- This will not work!

That would indeed give you a random number - in a way. What you truly need is a way to encode that you want a new pseudo-random number every time. This means information needs to go from one random number generation to the next. Most languages just ignore this "minor detail", but Haskell forces you to pay attention. You might thank Haskell when you find yourself in the spot to properly reproduce your pseudo-random result in a multi-threaded context.

There's a number of ways you can make these connections, most of which have been mentioned already. If you are reluctant to use a monad: Note that it might generally be a good thing to have your code in a monadic form (but not using IO!). Down the road, you might well come into situations where you want more monad features, such as a reader for configuration - then all ground work would be done already.

share|improve this answer
There should be a way to mark code as non-solutions. Because it's too easy to just see the grey box and think that's the answer. –  augustss Sep 7 '11 at 12:51
@augustss, huh? I'm not sure how to take your comment. The question was "Is there something simple like this?". A small illustration just seemed like a good idea. –  Peter Wortmann Sep 7 '11 at 13:35
Yeah, but this simple illustration, while it "works", will be considered wrong by a good 99% of the community. I think @augustss would like to draw attention to that fact. –  luqui Sep 7 '11 at 19:01
@Peter I was just making a general remark about stackoverflow. Sometimes you want to make code fragments that illustrate how not to do something. I can see from your answer that you are not suggesting that this is the right way. I'm just worried that people might not read the text and just copy the code. –  augustss Sep 8 '11 at 10:53
Okay, fair point. I added a code comment to reflect that. –  Peter Wortmann Sep 8 '11 at 11:15
add comment

I think, "you will have to live with that", is neither useful nor correct. It really depends on the abstractions you are using. If your application is naturally bound to a monad, then it makes sense to use a monadic random number generator, which is just as convenient as Java's random number generator.

In the case of a game using modern abstractions your application is naturally bound to functional reactive programming (FRP), where generating random numbers is no problem at all and doesn't require you to pass around generators explicitly. Example using the netwire library:

movingPoint :: MonadIO m => (Double, Double) -> Wire m a (Double, Double)
movingPoint x0 =
    proc _ -> do
        -- Randomly fades in and out of existence.
        visible <- wackelkontakt -< ()
        require -< (visible, ())

        -- 'rnd' is a random value between -1 and 1.
        rnd <- noise1 -< ()

        -- dx is the velocity.
        let dx = (sin &&& cos) (rnd * pi)

        -- Integration of dx over time gives us the point's position.
        -- x0 is the starting point.
        integral x0 -< dx

Is there any way to express this easier and more concisely? I guess not. FRP also proves Zhen's comment wrong. It can handle user input purely.

share|improve this answer
add comment

Believe it or not, you'll have to use different approaches in Haskell than you did in Java. There are a couple packages that can help you, but you will have to get a different attitude in your head to use them successfully. Here are some pointers:

Searching for the word "random" on Hackage's package list will turn up many, many more specific packages for more specific needs.

share|improve this answer
You don't "have to". You can use IO everywhere as you did in Java. –  Rotsor Sep 7 '11 at 9:06
@Rotsor: Although unless you also put everything into ST (monad transformers are fun), you still need to cope with immutability. And even then it's rather ugly and pointless, so much that I'd expect any sane programmer to abandon it. –  delnan Sep 7 '11 at 9:41
@delnan, I agree that it's ugly and pointless (the same way programming in Java is), but don't see how ST is necessary. IO can do everything ST can and more. –  Rotsor Sep 7 '11 at 10:01
@Rotsor Except that IO can't encapsulate the effects, which is the whole point of ST. –  augustss Sep 7 '11 at 12:50
@augustss: Ah, but encapsulating effects isn't a matter of what IO can't do! Rather, it's about what IO can't not do. Not doing things in very precise ways is more difficult, yet often more effective, than simply doing whatever one pleases all the time. –  C. A. McCann Sep 8 '11 at 22:10
add comment

Sorry, but you will have to live with that. How can there be a function in a pure functional language that gives you different values on each call? Answer is: it cannot - only in the IO-Monad or something similiar like the state-monad where you can pass your seed around (and don't have the same input every time) can such a things exist.

You may alsow have a look as this question "How can a time function exist in functional programming?" as it's in the same direction as yours.

share|improve this answer
I down voted you because you didn't really give a solution. The obvious solution is to use MonadRandom –  Axman6 Sep 7 '11 at 8:10
well thank you ... but the question was if there is something simple and he don't like IO Monad ... do you think MonadRandom is so much better then? –  Carsten König Sep 7 '11 at 8:14
@Carsten, of course it is much better because it does not allow arbitrary IO. –  Rotsor Sep 7 '11 at 9:08
nevermind ... I had the understanding that the OP don't wanted to enter "monad"-zone or "do"-notation or whatever at all –  Carsten König Sep 7 '11 at 9:36
add comment

Your Answer


