Let’s say I want to generate a random number in Haskell. To do so, I’ll make use of
randomRIO (0, 10)
that generates a number between 0 and 10 for me. It’s type is
randomRIO (0,10) :: (Random a, Num a) => IO a
Now, let’s say I assign its result to a value k. It’s type is IO Integer.
Trying to do usual arithmetic stuff such as k + 2 will yield the following result in Ghci:
<interactive>:1:3:
No instance for (Num (IO Integer))
arising from the literal `2'
Possible fix: add an instance declaration for (Num (IO Integer))
In the second argument of `(+)', namely `2'
In the expression: k + 2
In an equation for `it': it = k + 2
The problem also happens when trying asking Ghci about
[randomRIO (0, 10) | x <- [0..10]]
The error message is a bit cryptic, how can I make use of random numbers in Haskell?
A value of type
IO Integeris not an integer. It’s an action that, when performed, will return an integer. The distinction is important. The only way to performIOactions is to hook them up tomain, or type them into GHCi.So
randomRIO (0, 10)is an action, that when performed, returns a random number between0and10. Note that this is not a function, as a function must always return the same result given the same input, although we sometimes call this an impure function.So the question is, how do you take an action returning an integer and make an action returning an integer plus two? Easy, you can use
fmapto combine an action and a pure function transforming its result into a new action.Control.Monadcontains many useful functions for building new actions out of other actions. For your second example, we can usereplicateM, which creates an action that, when performed, runs the original action multiple times, collecting the results into a list:You can also obtain similar results manually using
do-notation.For more information, you should read up on monads, for example in Learn You a Haskell.