
I wish I'd known this when I was first beginning, but it is possible
to do randomness outside of IO, surprisingly easily. I like to use
the monadRandom library, which provides some monads and monad
transformers for this task. I too became frustrated when I wrote a
roguelike but could not figure out how to inject randomness into it
when I wanted. A program you would write might be like this:
data Obstacle = Mon (Int, Int) Monster | Door (Int, Int) | Trap (Int,
Int) deriving (Show, Enum)
data Monster = Orc | Wolf | Dragon deriving (Show, Enum)
main = do
print =<< evalRandIO randomObstacle
randomObstacle :: RandomGen g => Rand g Obstacle
randomObstacle = do
x <- getRandomR (0,2::Int)
case x of
0 -> Mon <$> randomLocation <*> randomMonster
1 -> Door <$> randomLocation
2 -> Trap <$> randomLocation
randomLocation :: RandomGen g => Rand g (Int,Int)
randomLocation = do
x <- getRandomR (0,10)
y <- getRandomR (0,10)
return (x,y)
randomMonster :: RandomGen g => Rand g Monster
randomMonster = do
x <- getRandomR (0,2::Int)
return $ case x of
0 -> Orc
1 -> Dragon
2 -> Wolf
This way, even though my randomBlah functions do not have IO in them,
nor do they pass around a stdGen around, but they can be combined
willy nilly as needed, and only computed when you want them to. I
also could have made Random instances for Obstacle and Monster so that
I did not have to do the cases in the code, making things easier to
understand.
On Fri, Dec 9, 2011 at 3:27 PM, Brent Yorgey
Does "impurity" from something like a random number generator or file I/O have to move it's way all the way through my code?
No, only through the parts that actually have to do file I/O or generate random numbers or whatever. However, cleanly separating the IO code from the non-IO/"pure" code takes some experience. It does seem to be a common experience of people learning Haskell that IO ends up "infecting" everything, even stuff that shouldn't have to do any IO, but with good design this is not necessary.
In your particular case, your matrix generation function does depend on random number generation so it makes sense that its type must involve IO. However, if you go on to write other functions which do deterministic operations on matrices, their types should *not* involve IO, even if you pass randomly generated matrices to them as arguments.
-Brent
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners