```
module WhyNoIOinput where
import System.Random
```

Our toy example for this note: We want to generate two random numbers and then
output their sum and product. We learned before that random stuff in Haskell
needs this scary thing called `IO`

monad, so we expect this to be difficult.

First we need something to generate random numbers:

```
makeInt :: IO Int
= randomRIO (1,10) :: IO Int makeInt
```

Now, let's add and multiply them.

```
sumIO :: IO Int -> IO Int -> IO Int
= do
sumIO makeX makeY <- makeX
x <- makeY
y return (x+y)
productIO :: IO Int -> IO Int -> IO Int
= do
productIO makeX makeY <- makeX
x <- makeY
y return (x*y)
```

```
sumAndProductIO :: IO Int -> IO Int -> IO (Int,Int)
= do
sumAndProductIO makeX makeY <- sumIO makeX makeY
s <- productIO makeX makeY
p return (s,p)
```

```
example1 :: IO ()
= do
example1 <- sumAndProductIO makeInt makeInt
(s,p) putStrLn $ "Sum:" ++ show s
putStrLn $ "Product:" ++ show p
```

So, what do we get?

```
*WhyNoIOinput> example1
Sum:9
Product:4
*WhyNoIOinput> example1
Sum:13
Product:21
```

But wait, if 21 = x * y, then we can never have x + y = 13.

So, what is going wrong here?

The problem is that `makeInt`

is not evaluated inside example1. And also
the `sumAndProductIO`

function does not run it to get concrete values but
is just handing it over to `sumIO`

and `productIO`

.

Imagine I have a calculator with a random number button. Then I can push
the button and then tell you the result. Or I can give you the calculator
and you push the button yourself. The difference seems unimportant and
indeed it is irrelevant *if* we are only interested in you getting to know
*one* value. But if I also want to give a random number to someone else
then it matters: Do I push the button and then give you and your friend
the *same number* or do I give the same calculator, i.e. merely the
*same way to generate a number* to both of you and you push the buttons
which can result in different numbers.

We can see what is happening if we use a function that always shows the random numbers it generates:

```
makeIntVerbose :: IO Int
= do
makeIntVerbose <- randomRIO (1,10)
x putStrLn $ "generated a random number: " ++ show x
return x
```

```
example2 :: IO ()
= do
example2 <- sumAndProductIO makeIntVerbose makeIntVerbose
(s,p) putStrLn $ "Sum:" ++ show s
putStrLn $ "Product:" ++ show p
```

This gives us:

```
*WhyNoIOinput> example2
generated a random number: 3
generated a random number: 1
generated a random number: 10
generated a random number: 7
Sum:4
Product:70
*WhyNoIOinput> example2
generated a random number: 4
generated a random number: 9
generated a random number: 10
generated a random number: 2
Sum:13
Product:20
```

Now it becomes clear that instead of two we always generate four random numbers. Then we get the sum of the first two and the product of the latter two.

Lesson learned: We often do not want `IO Int`

as an input type.

So, what is the proper way to do it?

First, realise that many of your functions are actually pure!

```
sumAndProduct :: Int -> Int -> (Int,Int)
= (x+y,x*y) sumAndProduct x y
```

Use a wrapper function which collects the *results* of IO functions
and then feeds them into the pure function and returns the result.

```
randomSumAndProduct :: IO (Int,Int)
= do
randomSumAndProduct <- makeInt
x <- makeInt
y let sap = sumAndProduct x y
return sap
```

This gives:

```
*WhyNoIOinput> randomSumAndProduct
(19,90)
*WhyNoIOinput> randomSumAndProduct
(12,27)
```

Try replacing `makeInt`

with `makeIntVerbose`

.

Final note: Make sure you understand the difference between `x <- makeInt`

and `let x = makeInt`

. In the latter variant, x will still be a way to get
a value and not a concrete single fixed value!