[Haskell-beginners] IO ( stuff )
Paul Monday
paul.monday at parsci.com
Mon Dec 12 18:16:37 CET 2011
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 at 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 <byorgey at seas.upenn.edu> 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 at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
More information about the Beginners
mailing list