
Thank you SO much for the discussion. I've learned quite a bit over the course of it. As one would expect, lifting wasn't my only issue … I had some rather annoying Unbox / Boxed / [] problems with the recursion. I stepped way back finally this morning to think about the problem and the discussion points. I was able to make use of laziness with the randomRs function. randomRs is nice since there are no side-effects, I get an "infinite" list of random numbers that can easily be broken into rows and matrices lazily. So, here is how I generated two square matrices with rows and columns = n (some other artifacts are included here as well, like the Matrix type I'm using) data Matrix a = Matrix (V.Vector (U.Vector a)) deriving (Show, Eq) makematrix :: [Float] -> Int -> Int -> [U.Vector Float] makematrix xs n 0 = [] makematrix xs n r = (U.fromList $ ys) : makematrix zs n (r - 1) where (ys, zs) = splitAt n xs main :: IO () main = do args <- getArgs let n = read (args !! 0) :: Int let minrange = read (args !! 1) :: Float let maxrange = read (args !! 2) :: Float let s = read (args !! 3) :: Int let g = mkStdGen s let range = (minrange, maxrange) let all = randomRs range g let ma = Matrix $ (V.fromList (makematrix all n n)) let mb = Matrix $ (V.fromList (makematrix (drop (n*n) all) n n)) ... As with all Haskell I'm learning, I'm 100% sure there are quite a few better ways to write this ;-) Still, again, I can't thank you enough for the thoughtful discussion on IO and randomness. I have avoided running back to Java with my tail between my legs for another day. Paul Monday Parallel Scientific, LLC. paul.monday@parsci.com On Dec 9, 2011, at 3:05 PM, David McBride wrote:
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
wrote: 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
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners