
On Tue, Mar 22, 2011 at 5:46 AM, Adrian May
OK I did this:
import System.Random
walk :: Int -> IO Int walk i = randomRIO (0,1) >>= \r -> return (i+r*2-1)
say :: Int -> IO () say i = putStrLn $ show i
rep :: Int -> a -> (a -> IO a) -> (a -> IO ()) -> IO () rep n i w s | n<=0 = return () | otherwise = s i >> w i >>= \ii -> rep (n-1) ii w s
main :: IO () main = rep 10 50 walk say
Is that the easiest way?
I don't know about "easiest", it's not bad though there are thing that can be improved
say i = putStrLn $ show i
This already exist and is called "print" (though its type is more general than your signature).
walk i = randomRIO (0,1) >>= \r -> return (i+r*2-1)
The >>= ... return is pretty ugly, it would rather be written as :
walk i = fmap (\r -> i + r * 2 - 1) $ randomRIO (0,1)
rep n i w s
Passing say and walk as parameter seems a bit overkill, I seriously doubt that you'll ever need this exact structure again, and even then passing a single action should be enough :
rep n act i | n <= 0 = return () | otherwise = act i >>= \x -> rep (n-1) act x
rep may also be written with standard monad operations :
rep n act i = foldM (\x _ -> act x) i $ replicate (n-1) ()
Lastly it may be that the structure of the program itself, particularly the use of randomRIO is suboptimal and a bit ugly, for a throwaway program I would probably just use randomRs :
main = do g <- newStdGen mapM_ print . tail . scanl (\i r -> i+r*2-1) 50 . take 10 $ randomRs (0,1) g
but for a more complex endeavour I would rather use a serious library like mwc-random. (System.Random performances are awful) -- Jedaï