[Haskell-beginners] Recursion in monad
Chaddaï Fouché
chaddai.fouche at gmail.com
Tue Mar 22 21:44:20 CET 2011
On Tue, Mar 22, 2011 at 5:46 AM, Adrian May
<adrian.alexander.may at gmail.com> wrote:
> 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ï
More information about the Beginners
mailing list