[Haskell-cafe] Random numbers / monads - beginner question

Sebastian Sylvan sebastian.sylvan at gmail.com
Thu May 8 09:55:25 EDT 2008


2008/5/8 Madoc <madocdoyu at gmail.com>:

> Hello,
>
> I am just learning Haskell. Now, I encountered something that I cannot
> solve by myself. Your advice will be greatly appreciated.
>
> Given a list of numbers, I want to modify each of those numbers by adding a
> random offset. However, each such modified number shall stay within certain
> bounds, given by the integers minValue and maxValue. After that, I want to
> continue computation with the resulting list of type [Int]. But for
> demonstration, I made a program that just prints out the list:
>
> import IO; import Random
>
> minValue = 0::Int
> maxValue = 1000::Int
>
> normalize a | a < minValue = minValue
>             | a > maxValue = maxValue
>             | otherwise = a
>
> modify a = do
>   offset <- randomRIO(-100::Int, 100)
>   return(normalize(a + offset))
>
> main = putStrLn $ show $ map (modify) [0, 200, 400, 600, 800, 1000]
>
> This program will not compile. GHC complains:
>
> test.hs:14:18:
>     No instance for (Show (IO Int))
>       arising from a use of `show' at test.hs:14:18-21
>     Possible fix: add an instance declaration for (Show (IO Int))
>     In the first argument of `($)', namely `show'
>     In the second argument of `($)', namely
>         `show $ map (modify) [0, 200, 400, 600, ....]'
>     In the expression:
>           putStrLn $ show $ map (modify) [0, 200, 400, 600, ....]
>
> I understand that the result of the modify function is not an Int, as I
> would like to have it, but instead IO Int, and that cannot be applied to
> show. (I also did not quite understand why I need those brackets around
> the return value of the modify value. It won't compile if I leave them
> out, but I can accept that for now.)
>
> I also figured out how to generate a modified list of type [IO Int] and of
> type IO [Int]. However, I could not find out how to completely get rid of
> the IO monad and just get a mofied list of type [Int], which is what I
> really want.
>
> Please, do You have any advice for me? I tried for some hours, and now I am
> really angry at that IO monad that sticks to my pretty integers like glue!
>
> Also, any comment on the programming style and how I could achive my goals
> easier would be appreciated. (I left out comments and function types for the
> sake of brevity.)
>

You should use newStdGen to produce a random generator, then randomRs to
produce a list of random numbers (without using IO!).

But if you really want this version with IO interspersed through the
algorithm to work, then something like this should do it (uncompiled):

main = do
 xs <- mapM  (modify) [0, 200, 400, 600, 800, 1000]
 putStrLn $ show $ xs

The only way to "get rid of the IO monad", is to use "<-" to bind it to a
value from within the IO monad.



-- 
Sebastian Sylvan
+44(0)7857-300802
UIN: 44640862
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20080508/e918498b/attachment.htm


More information about the Haskell-Cafe mailing list