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

2008-05-08 Thread Claude Heiland-Allen

Madoc wrote:

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].


Personally, I'd do something like this, isolate the IO code outside the 
algorithm to keep the algorithm pure:



modify' :: Int - Int - Int
modify' offset a =  normalize (a + offset)

generateInfiniteListOfRandomNumbers :: IO [Int]
-- implementation left as an exercise

main = do
  randomNumbers - generateInfiniteListOfRandomNumbers
  print $ zipWith modify' randomNumbers [0, 200, 400, 600, 800, 1000]


hope this helps,


Claude
--
http://claudiusmaximus.goto10.org
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


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

2008-05-08 Thread Thomas Dinsdale-Young
 Madoc wrote:

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].


Personally, I'd do something like this, isolate the IO code outside the
algorithm to keep the algorithm pure:


modify' :: Int - Int - Int
modify' offset a =  normalize (a + offset)

generateInfiniteListOfRandomNumbers :: IO [Int]
-- implementation left as an exercise

main = do
  randomNumbers - generateInfiniteListOfRandomNumbers
  print $ zipWith modify' randomNumbers [0, 200, 400, 600, 800, 1000]

I may be wrong, but generateInfiniteListOfRandomNumbers won't terminate and
I think it has to before the next IO action occurs.  (Laziness is great, but
I don't think you can really do lazy IO like that.)

Instead of map :: (a - b) - [a] - [b], I think you are looking for mapM
:: Monad m = (a - m b) - [a] - m [b].
* *
* *Hope this helps,
Thomas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


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

2008-05-08 Thread Brent Yorgey
2008/5/8 Thomas Dinsdale-Young [EMAIL PROTECTED]:

 Madoc wrote:

 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].


 Personally, I'd do something like this, isolate the IO code outside the
 algorithm to keep the algorithm pure:


 modify' :: Int - Int - Int
 modify' offset a =  normalize (a + offset)

 generateInfiniteListOfRandomNumbers :: IO [Int]
 -- implementation left as an exercise

 main = do
   randomNumbers - generateInfiniteListOfRandomNumbers
   print $ zipWith modify' randomNumbers [0, 200, 400, 600, 800, 1000]

 I may be wrong, but generateInfiniteListOfRandomNumbers won't terminate
 and I think it has to before the next IO action occurs.  (Laziness is great,
 but I don't think you can really do lazy IO like that.)


Sure it will.  You're right that you cannot do lazy IO like this, but no
lazy IO needs to happen here.  The key is that an IO action does not have to
be performed in order to generate each element of the list -- one IO action
is performed at the beginning to produce a random generator, and then this
generator is used (functionally and purely) to produce a lazy infinite list
of pseudorandom numbers.  For example see the 'newStdGen' and 'randoms'
functions from System.Random.

-Brent
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


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

2008-05-08 Thread Henning Thielemann


On Thu, 8 May 2008, Madoc wrote:


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



normalize = min maxValue . max minValue



modify a = do
 offset - randomRIO(-100::Int, 100)
 return(normalize(a + offset))



Stay away from IO whereever possible, use randomR instead.
Say
  map normalize (zipWith (+) (randomRs (-100::Int, 100)) x)

http://haskell.org/haskellwiki/Humor/Erlkönig
http://haskell.org/haskellwiki/Things_to_avoid#Separate_IO_and_data_processing___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


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

2008-05-08 Thread Sebastian Sylvan
2008/5/8 Madoc [EMAIL PROTECTED]:

 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
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


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

2008-05-08 Thread Dan Weston

Henning Thielemann wrote:


On Thu, 8 May 2008, Madoc wrote:


minValue = 0::Int
maxValue = 1000::Int

normalize a | a  minValue = minValue
   | a  maxValue = maxValue
   | otherwise = a



normalize' = min maxValue . max minValue


There is a curiosity here. The functions normalize and normalize' are 
extensionally equal only because minValue = maxValue, but intensionally 
different. The intensional equivalent is to reverse order of composition:


normalize'' = max minValue . min maxValue

which remains equal to to normalize whatever the values of minValue and 
maxValue.


That the order of composition (or of guarded expressions) matters 
conditionally base on its parameters is reason enough for the original 
poster to decide what the right answer should be if maxValue  
minValue. These corner cases are often where future bugs lie dormant. My 
choice would be:


normalize'''= max trueMin . min trueMax
  where trueMin = min minValue maxValue
trueMax = max minValue maxValue

Now the function makes no assumptions about external values. This is no 
less efficient than before, since trueMin and trueMax are CAFs evaluated 
only once.



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe