[Haskell-cafe] Help mixing pure and IO code
Luke Palmer
lrpalmer at gmail.com
Mon Nov 30 22:53:44 EST 2009
On Mon, Nov 30, 2009 at 8:36 PM, Hector Guilarte <hectorg87 at gmail.com> wrote:
> One time I needed to do use a random number in some places of a completly
> pure program so I made a infinite list of random numbers and passed it
> around all the time in the functions as they where called, using the head of
> the list I passed to the function whenever I needed a random number and
> returning a tuple which it's second element was the tail of the random
> numbers list e.g.
>
> f:: [int] -> (a,[Int])
> f randomList =
> let usedRandomNumber = g $ head randomList
> in (usedRandomNumber,(tail randomList))
>
> or even something like:
> f:: [int] -> (a,[Int])
> f randomList =
> let (usedRandomNumber,newRandomList) = g randomList
> in (usedRandomNumber,newRandomList)
This pattern can be encapsulated in a monad:
newtype RandM a = RandM { unRandM :: [Int] -> (a,[Int]) }
instance Monad RandM where
return x = RandM $ \randomList -> (x, randomList)
m >>= g = RandM $ \randomList ->
let (x, newRandomList) = unRandM m randomList
in unRandM (g x) newRandomList
getRandom :: RandM Int
getRandom = RandM $ \(randomNumber:randomList) -> (randomNumber, randomList)
See the similarity?
Of course, there is no need to implement this yourself. It is already
implemented as State [Int]. And as long as you are doing that, you
might as well use Rand from the MonadRandom package. In fact, I have
argued that you should use MonadRandom instead of the lower-level
System.Random whenever possible:
http://lukepalmer.wordpress.com/2009/01/17/use-monadrandom/
Luke
More information about the Haskell-Cafe
mailing list