I am currently learning Haskell and I have a hard time to see What are the common ways to save intermediaries result in Haskell.
For example, let's say that I have a program that take a file, produce some intermediary results and then take some parameters and use the result of the first step to produce something else. Plus, let's say that at the end the user could change the parameters to produce new output but the processing of the first step should not be redone in order to reduce the computation time.
Basically, I just need to temporally save the result of the first step. This would be fairly simple for me in a OO way but because of Haskell purity I don't see a convenient way to solve this.
There are many ways to deal with intermediate results in Haskell. It sounds to me like you would like your main function to look something like this. I will assume you have some function that produces an intermediate result (runFirstStep), a function that prompts for settings (promptForSettings), and a function that uses the intermediate result and the settings to produce a final value (runSecondStep)
main :: IO ()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- processing
-- prompt for settings here
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- and done
print final
If you want a more complex control-flow, you could define a separate function, like so:
main :: IO ()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- run the second step computation
processLoop intermediate
print final
processLoop :: intermediate -> IO final
processLoop intermediate = do
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- check if user wants to run with different settings
rerun <- do
putStrLn "Run again? [Y/n]"
result <- getStrLn
return (result != "n")
if rerun
then process
else return final
If you are interested in more complex control flows that are impure, there are many ways to store intermediate computations in memory using a variety of techniques. The lowest level and most difficult to get right is to use IORef. Above that, you can use MVar as a way of signalling and locking sections of code based on some shared state, but even that can be tricky to get right. At the highest level, ST and STM let you handle shared state in much more complex ways and are easier to reason about.
An example: You want to read in a bunch of numbers and then compute different sums of powers of those numbers (sums of squares, sums of cubes, etc.)
The first step is to "ignore the IO" - forget for the moment how you are going to get the numbers and the power parameter - and concentrate on the function that does meat of the work - computes the sums of n-th powers of a list of numbers.
powersum :: [Double] -> Int -> Double
powersum xs n = sum $ map (^n) xs
We'll want to compute power sums for various exponents. Again, I would forget about what you are going to do with them later, whether it be print them out, sort them, etc. and write a function which does the computation:
powersums :: [Double] -> [Int] -> [Double]
powersums xs ns = map (powersum xs) ns
Now let's hook it up to the real world. Let's first consider the case when we know the exponents in advance but read the numbers from standard input (all on a single line.)
main = do line <- getLine -- IO
let nums = map read (words line) \
let exponents = [1..10] | - pure code
let sums = powersums nums exponents /
print sums -- IO
Note how our IO sandwiches our pure code - this is very typical of functional programs.
Now suppose you want to also read in the exponents from stdin, and print out the power sums of each read exponent. You could write an imperative-style program like this:
main = do line <- getLine
let nums = map read (words line)
forever $ do exp <- read `fmap` getLine
putStrLn $ show $ powersum nums exp
This illustrates how data (nums in this case) is being stored for use by other parts of the program.
Related
main = do
input <- sequence [getLine, getLine, getLine]
mapM_ print input
Let's see this program in action:
m#m-X555LJ:~$ runhaskell wtf.hs
asdf
jkl
powe
"asdf"
"jkl"
"powe"
Surprisingly to me, there seems to be no laziness here. Instead, all 3 getLines are evaluated eagerly, the read values are stored in memory and then, not before, all are printed.
Compare to this:
main = do
input <- fmap lines getContents
mapM_ print input
Let's see this in action:
m#m-X555LJ:~$ runhaskell wtf.hs
asdf
"asdf"
lkj
"lkj"
power
"power"
Totally different stuff. Lines are read one by one and printed one by one. Which is odd to me because I don't really see any differences between these two programs.
From LearnYouAHaskell:
When used with I/O actions, sequenceA is the same thing as sequence!
It takes a list of I/O actions and returns an I/O action that will
perform each of those actions and have as its result a list of the
results of those I/O actions. That's because to turn an [IO a] value
into an IO [a] value, to make an I/O action that yields a list of
results when performed, all those I/O actions have to be sequenced so
that they're then performed one after the other when evaluation is
forced. You can't get the result of an I/O action without performing
it.
I'm confused. I don't need to perform ALL IO actions to get the results of just one.
A few paragraphs earlier the book shows a definition of sequence:
sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
Nice recursion; nothing here hints me that this recursion should not be lazy;just like in any other recursion, to get the head of the returned list Haskell doesn't have to go down through ALL steps of recursion!
Compare:
rec :: Int -> [Int]
rec n = n:(rec (n+1))
main = print (head (rec 5))
In action:
m#m-X555LJ:~$ runhaskell wtf.hs
5
m#m-X555LJ:~$
Clearly, the recursion here is performed lazily, not eagerly.
Then why is the recursion in the sequence [getLine, getLine, getLine] example performed eagerly?
As to why it is important that IO actions are run in order
regardless of the results: Imagine an action createFile :: IO () and
writeToFile :: IO (). When I do a sequence [createFile,
writeToFile] I'd hope that they're both done and in order, even
though I don't care about their actual results (which are both the
very boring value ()) at all!
I'm not sure how this applies to this Q.
Maybe I'll word my Q this way...
In my mind this:
do
input <- sequence [getLine, getLine, getLine]
mapM_ print input
should detoriate to something like this:
do
input <- do
input <- concat ( map (fmap (:[])) [getLine, getLine, getLine] )
return input
mapM_ print input
Which, in turn, should detoriate to something like this (pseudocode, sorry):
do
[ perform print on the result of getLine,
perform print on the result of getLine,
perform print on the result of getLine
] and discard the results of those prints since print was applied with mapM_ which discards the results unlike mapM
getContents is lazy, getLine isn't. Lazy IO isn't a feature of Haskell per se, it's a feature of some particular IO actions.
I'm confused. I don't need to perform ALL IO actions to get the results of just one.
Yes you do! That is one of the most important features of IO, that if you write a >> b or equivalently,
do a
b
then you can be sure that a is definitely "run" before b (see footnote). getContents is actually the same, it "runs" before whatever comes after it... but the result it returns is a sneaky result that sneakily does more IO when you try to evaluate it. That is actually the surprising bit, and it can lead to some very interesting results in practice (like the file you're reading the contents of being deleted or changed while you're processing the results of getContents), so in practical programs you probably shouldn't be using it, it mostly exists for convenience in programs where you don't care about such things (Code Golf, throwaway scripts or teaching for instance).
As to why it is important that IO actions are run in order regardless of the results: Imagine an action createFile :: IO () and writeToFile :: IO (). When I do a sequence [createFile, writeToFile] I'd hope that they're both done and in order, even though I don't care about their actual results (which are both the very boring value ()) at all!
Addressing the edit:
should detoriate to something like this:
do
input <- do
input <- concat ( map (fmap (:[])) [getLine, getLine, getLine] )
return input
mapM_ print input
No, it actually turns into something like this:
do
input <- do
x <- getLine
y <- getLine
z <- getLine
return [x,y,z]
mapM_ print input
(the actual definition of sequence is more or less this:
sequence [] = return []
sequence (a:as) = do
x <- a
fmap (x:) $ sequence as
Technically, in
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
we find <*>, which first runs the action on the left, then the action on the right, and finally applies their result together. This is what makes the first effect in the list to be occur first, and so on.
Indeed, on monads, f <*> x is equivalent to
do theF <- f
theX <- x
return (theF theX)
More in general, note that all the IO actions are generally executed in order, first to last (see below for a few rare exceptions). Doing IO in a completely lazy way would be a nightmare for the programmer. For instance, consider:
do let aX = print "x" >> return 4
aY = print "y" >> return 10
x <- aX
y <- aY
print (x+y)
Haskell guarantees that the output is x y 14, in that order. If we had completely lazy IO we could also get y x 14, depending on which argument is forced first by +. In such case, we would need to know exactly the order in which the lazy thunks are demanded by every operation, which is something the programmer definitely does not want to care about. Under such detailed semantics, x + y is no longer equivalent to y + x, breaking equational reasoning in many cases.
Now, if we wanted to force IO to be lazy we could use one of the forbidden functions, e.g.
do let aX = unsafeInterleaveIO (print "x" >> return 4)
aY = unsafeInterleaveIO (print "y" >> return 10)
x <- aX
y <- aY
print (x+y)
The above code makes aX and aY lazy IO actions, and the order of the output is now at the whim of the compiler and the library implementation of +. This is in general dangerous, hence the unsafeness of lazy IO.
Now, about the exceptions. Some IO actions which only read from the environment, like getContents were implemented with lazy IO (unsafeInterleaveIO). The designers felt that for such reads, lazy IO can be acceptable, and that the precise timing of the reads is not that important in many cases.
Nowadays, this is controversial. While it can be convenient, lazy IO can be too unpredictable in many cases. For instance, we can't know where the file will be closed, and that could matter if we're reading from a socket. We also need to be very careful not to force the reads too early: that often leads to a deadlock when reading from a pipe. Today, it is usually preferred to avoid lazy IO, and resort to some library like pipes or conduit for "streaming"-like operations, where there is no ambiguity.
I would like to allow a user to build a list from a series of inputs in Haskell.
The getLine function would be called recursively until the stopping case ("Y") is input, at which point the list is returned.
I know the function needs to be in a similar format to below. I am having trouble assigning the correct type signatures - I think I need to include the IO type somewhere.
getList :: [String] -> [String]
getList list = do line <- getLine
if line == "Y"
then return list
else getList (line : list)
So there's a bunch of things that you need to understand. One of them is the IO x type. A value of this type is a computer program that, when later run, will do something and produce a value of type x. So getLine doesn't do anything by itself; it just is a certain sort of program. Same with let p = putStrLn "hello!". I can sequence p into my program multiple times and it will print hello! multiple times, because the IO () is a program, as a value which Haskell happens to be able to talk about and manipulate. If this were TypeScript I would say type IO<x> = { run: () => Promise<x> } and emphatically that type says that the side-effecting action has not been run yet.
So how do we manipulate these values when the value is a program, for example one that fetches the current system time?
The most fundamental way to chain such programs together is to take a program that produces an x (an IO x) and then a Haskell function which takes an x and constructs a program which produces a y (an x -> IO y and combines them together into a resulting program producing a y (an IO y.) This function is called >>= and pronounced "bind". In fact this way is universal, if we add a program which takes any Haskell value of type x and produces a program which does nothing and produces that value (return :: x -> IO x). This allows you to use, for example, the Prelude function fmap f = (>>= return . f) which takes an a -> b and applies it to an IO a to produce an IO b.
So It is so common to say things like getLine >>= \line -> putStrLn (upcase line ++ "!") that we invented do-notation, writing this as
do
line <- getLine
putStrLn (upcase line ++ "!")
Notice that it's the same basic deal; the last line needs to be an IO y for some y.
The last thing you need to know in Haskell is the convention which actually gets these things run. That is that, in your Haskell source code, you are supposed to create an IO () (a program whose value doesn't matter) called Main.main, and the Haskell compiler is supposed to take this program which you described, and give it to you as an executable which you can run whenever you want. As a very special case, the GHCi interpreter will notice if you produce an IO x expression at the top level and will immediately run it for you, but that is very different from how the rest of the language works. For the most part, Haskell says, describe the program and I will give it to you.
Now that you know that Haskell has no magic and the Haskell IO x type just is a static representation of a computer program as a value, rather than something which does side-effecting stuff when you "reduce" it (like it is in other languages), we can turn to your getList. Clearly getList :: IO [String] makes the most sense based on what you said: a program which allows a user to build a list from a series of inputs.
Now to build the internals, you've got the right guess: we've got to start with a getLine and either finish off the list or continue accepting inputs, prepending the line to the list:
getList = do
line <- getLine
if line == 'exit' then return []
else fmap (line:) getList
You've also identified another way to do it, which depends on taking a list of strings and producing a new list:
getList :: IO [String]
getList = fmap reverse (go []) where
go xs = do
x <- getLine
if x == "exit" then return xs
else go (x : xs)
There are probably several other ways to do it.
Consider the code below taken from a working example I've built to help me learn Haskell. This code parses a CSV file containing stock quotes downloaded from Yahoo into a nice simple list of bars with which I can then work.
My question: how can I write a function that will take a file name as its parameter and return an OHLCBarList so that the first four lines inside main can be properly encapsulated?
In other words, how can I implement (without getting all sorts of errors about IO stuff) the function whose type would be
getBarsFromFile :: Filename -> OHLCBarList
so that the grunt work that was being done in the first four lines of main can be properly encapsulated?
I've tried to do this myself but with my limited Haskell knowledge, I'm failing miserably.
import qualified Data.ByteString as BS
type Filename = String
getContentsOfFile :: Filename -> IO BS.ByteString
barParser :: Parser Bar
barParser = do
time <- timeParser
char ','
open <- double
char ','
high <- double
char ','
low <- double
char ','
close <- double
char ','
volume <- decimal
char ','
return $ Bar Bar1Day time open high low close volume
type OHLCBar = (UTCTime, Double, Double, Double, Double)
type OHLCBarList = [OHLCBar]
barsToBarList :: [Either String Bar] -> OHLCBarList
main :: IO ()
main = do
contents :: C.ByteString <- getContentsOfFile "PriceData/Daily/yhoo1.csv" --PriceData/Daily/Yhoo.csv"
let lineList :: [C.ByteString] = C.lines contents -- Break the contents into a list of lines
let bars :: [Either String Bar] = map (parseOnly barParser) lineList -- Using the attoparsec
let ohlcBarList :: OHLCBarList = barsToBarList bars -- Now I have a nice simple list of tuples with which to work
--- Now I can do simple operations like
print $ ohlcBarList !! 0
If you really want your function to have type Filename -> OHLCBarList, it can't be done.* Reading the contents of a file is an IO operation, and Haskell's IO monad is specifically designed so that values in the IO monad can never leave. If this restriction were broken, it would (in general) mess with a lot of things. Instead of doing this, you have two options: make the type of getBarsFromFile be Filename -> IO OHLCBarList — thus essentially copying the first four lines of main — or write a function with type C.ByteString -> OHLCBarList that the output of getContentsOfFile can be piped through to encapsulate lines 2 through 4 of main.
* Technically, it can be done, but you really, really, really shouldn't even try, especially if you're new to Haskell.
Others have explained that the correct type of your function has to be Filename -> IO OHLCBarList, I'd like to try and give you some insight as to why the compiler imposes this draconian measure on you.
Imperative programming is all about managing state: "do certain operations to certain bits of memory in sequence". When they grow large, procedural programs become brittle; we need a way of limiting the scope of state changes. OO programs encapsulate state in classes but the paradigm is not fundamentally different: you can call the same method twice and get different results. The output of the method depends on the (hidden) state of the object.
Functional programming goes all the way and bans mutable state entirely. A Haskell function, when called with certain inputs, will always produce the same output. Simple examples of
pure functions are mathematical operators like + and *, or most of the list-processing functions like map. Pure functions are all about the inputs and outputs, not managing internal state.
This allows the compiler to be very smart in optimising your program (for example, it can safely collapse duplicated code for you), and helps the programmer not to make mistakes: you can't put the system in an invalid state if there is none! We like pure functions.
The exception to the rule is IO. Code that performs IO is impure by definition: you could call getLine a hundred times and never get the same result, because it depends on what the user typed. Haskell handles this using the type system: all impure functions are marred with the IO type. IO can be thought of as a dependency on the state of the real world, sort of like World -> (NewWorld, a)
To summarise: pure functions are good because they are easy to reason about; this is why Haskell makes functions pure by default. Any impure code has to be labelled as such with an IO type signature; this tells the compiler and the reader to be careful with this function. So your function which reads from a file (a fundamentally impure action) but returns a pure value can't exist.
Addendum in response to your comment
You can still write pure functions to operate on data that was obtained impurely. Consider the following straw-man:
main :: IO ()
main = do
putStrLn "Enter the numbers you want me to process, separated by spaces"
line <- getLine
let numberStrings = words line
let numbers = map read numberStrings
putStrLn $ "The result of the calculation is " ++ (show $ foldr1 (*) numbers + 10)
Lots of code inside IO here. Let's extract some functions:
main :: IO ()
main = do
putStrLn "Enter the numbers you want me to process, separated by spaces"
result <- fmap processLine getLine -- fmap :: (a -> b) -> IO a -> IO b
-- runs an impure result through a pure function
-- without leaving IO
putStrLn $ "The result of the calculation is " ++ result
processLine :: String -> String -- look ma, no IO!
processLine = show . calculate . readNumbers
readNumbers :: String -> [Int]
readNumbers = map read . words
calculate :: [Int] -> Int
calculate numbers = product numbers + 10
product :: [Int] -> Int
product = foldr1 (*)
I've pulled logic out of main into pure functions which are easier to read, easier for the compiler to optimise, and more reusable (and so more testable). The program as a whole still lives inside IO because the data is obtained impurely (see the last part of this answer for a more thorough treatment of this argument). Impure data can be piped through pure functions using fmap and other combinators; you should try to put as little logic in main as possible.
Your code does seem to be most of the way there; as others have suggested you could extract lines 2-4 of your main into another function.
In other words, how can I implement (without getting all sorts of errors about IO stuff) the function whose type would be
getBarsFromFile :: Filename -> OHLCBarList
so that the grunt work that was being done in the first four lines of main can be properly encapsulated?
You cannot do this without getting all sorts of errors about IO stuff because this type for getBarsFromFile misses an IO. Probably that's what the errors about IO stuff are trying to tell you. Did you try understanding and fixing the errors?
In your situation, I would start by abstracting over the second to fourth line of your main in a function:
parseBars :: ByteString -> OHLCBarList
And then I would combine this function with getContentsOfFile to get:
getBarsFromFile :: FilePath -> IO OHLCBarList
This I would call in main.
I am a beginner to functional programming and Haskell as a programming language. After given an input of numbers from the command line I want to put those numbers into a list, then pass that list as a parameter to calculate its sum. Here's what I am working on:
import Data.List
iotxt :: IO ()
main :: IO ()
l1 = []
iotxt = do a <- getLine
-- read in numbers that are not equal to -1
insert (read a) l1
if (not ((read a) == -1.0))
then iotxt
else do return ()
main = do
putStrLn("Enter a number [-1 to quit]")
iotxt
-- size of the list
print(length [l1])
-- sum
But when I attempt to place the values inside the list I get this error:
Couldn't match expected type `IO a0' with actual type `[a1]'
In the return type of a call of `insert'
In a stmt of a 'do' block: insert (read a) l1
In the expression:
do { a <- getLine;
insert (read a) l1;
if (not ((read a) == - 1.0)) then iotxt else do { return () } }
There are multiple things wrong with you're code.
Starting from the bottom up, first, length [l1] doesn't make sense. Any [ ] with only one item in between is just that: a list with a single item, so the length will always be 1. You certainly mean length l1 here, i.e. length of the list l1, not length of the list ᴄᴏɴᴛᴀɪɴɪɴɢ only l1.
Next, you have this iotxt and try to make it modify the "global variable" l1. You can't do that, Haskell does not have any such thing as mutable global variables – for good reasons; global mutable state is considered evil even in imperative languages. Haskell kind of has local variables, through IORefs, but using those without good reason is frowned upon. You don't really need them for something like this here.
The correct thing to do is to scrap this global l1 binding, forget about mutating variables. Which brings us to the question of how to pass on the information acquired in iotxt. Well, the obvious functional thing to do is, returning it. We need to make that explicit in the type (which is again a good thing, so we actually know how to use the function):
ioTxt :: IO [Int]
Such a function can then nicely be used in main:
main :: IO ()
main = do
putStrLn "Enter a number [-1 to quit]"
l1 <- ioTxt
print $ length l1
You see: almost the same as your approach, but with proper explicit introduction of l1 where you need it, rather than somewhere completely different.
What's left to do is implementing ioTxt. This now also needs a local l1 variable since we have scrapped the global one. And when you implement a loop as such a recursive call, you need to pass an updated version of it to each instantiation. The recursion itself should be done on a locally-defined function.
ioTxt :: IO [Int]
ioTxT = go [] -- Start with empty list. `go` is a widespread name for such simple "loop functions".
where go l1 = do
a <- getLine
let x = read a :: Int
case x of
(-1) -> return l1
_ -> go (insert x l1)
In the last line, note that insert does not modify the list l1, it rather creates a new one that equals the old one except for having the new element in it. And then passes that to the next loop-call, so effectively you get an updated list for each recursive call.
Also note that you probably shouldn't use insert here: that's specifically for placing the new element at the right position in an ordered list. If you just want to accumulate the values in some way, you can simply use
_ -> go $ x : l1
In haskell, there are no variables, everything is immutable. So you shouldn't define l1 and change its value later, which doesn't work.
Instead you should think how to write iotxt properly and let it collect elements and pass the input list back to your main.
In your iotxt, you can think about these two situations:
if the input is -1, then we can just pass an empty list [] back, wrap it inside the IO by return []
if the input is not -1, we can first store this value somewhere, say result. After that, we should call iotxt recursively and let this inner iotxt handle the rest of the inputs. Finally, we will get return value rest, then we just simply put result and rest together.
Moreover, you can think of IO a like some program (which might have side effects like reading from input or writing to output) that returns a value of type a. According to the definition of your iotxt, which is a program that reads input until meeting a -1 and gives you the list in return, the type signature for iotxt should be IO [Float].
There's a length [l1] in your code, which constructs a list with only one element(i.e. l1) and thus length [l1] will always return 1. Instead of doing this, you can say length l1, which calculates the length of l1.
Finally, you don't need to group function arguments by parenthese, just simply say f x if you want to call f with x.
I've modified your code a little bit, hope it can give you some help.
import Data.List
-- iotxt reads from stdin, yields [Float]
-- stop reading when "-1" is read
iotxt :: IO [Float]
main :: IO ()
iotxt = do
a <- getLine
-- read in numbers that are not equal to -1
let result = (read a) :: Float
if (not (result == -1.0))
then do
-- read rest of the list from stdin
rest <- iotxt
-- put head & tail together
return $ result:rest
else do return []
main = do
putStrLn("Enter a number [-1 to quit]")
l1 <- iotxt
-- size of the list
print $ length l1
-- sum
print $ sum l1
I'm trying to spew out randomly generated dice for every roll that the user plays. The user has 3 rolls per turn and he gets to play 5 turns (I haven't implemented this part yet and I would appreciate suggestions).
I'm also wondering how I can display the colors randomly. I have the list of tuples in place, but I reckon I need some function that uses random and that list to match those colors. I'm struggling as to how.
module Main where
import System.IO
import System.Random
import Data.List
diceColor = [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
{-
randomList :: (RandomGen g) -> Int -> g -> [Integer]
random 0 _ = []
randomList n generator = r : randomList (n-1) newGenerator
where (r, newGenerator) = randomR (1, 6) generator
-}
rand :: Int -> [Int] -> IO ()
rand n rlst = do
num <- randomRIO (1::Int, 6)
if n == 0
then doSomething rlst
else rand (n-1) (num:rlst)
doSomething x = putStrLn (show (sort x))
main :: IO ()
main = do
--hSetBuffering stdin LineBuffering
putStrLn "roll, keep, score?"
cmd <- getLine
doYahtzee cmd
--rand (read cmd) []
doYahtzee :: String -> IO ()
doYahtzee cmd = do
if cmd == "roll"
then rand 5 []
else do print "You won"
There's really a lot of errors sprinkled throughout this code, which suggests to me that you tried to build the whole thing at once. This is a recipe for disaster; you should be building very small things and testing them often in ghci.
Lecture aside, you might find the following facts interesting (in order of the associated errors in your code):
List is deprecated; you should use Data.List instead.
No let is needed for top-level definitions.
Variable names must begin with a lower case letter.
Class prerequisites are separated from a type by =>.
The top-level module block should mainly have definitions; you should associate every where clause (especially the one near randomList) with a definition by either indenting it enough not to be a new line in the module block or keeping it on the same line as the definition you want it to be associated with.
do introduces a block; those things in the block should be indented equally and more than their context.
doYahtzee is declared and used as if it has three arguments, but seems to be defined as if it only has one.
The read function is used to parse a String. Unless you know what it does, using read to parse a String from another String is probably not what you want to do -- especially on user input.
putStrLn only takes one argument, not four, and that argument has to be a String. However, making a guess at what you wanted here, you might like the (!!) and print functions.
dieRoll doesn't seem to be defined anywhere.
It's possible that there are other errors, as well. Stylistically, I recommend that you check out replicateM, randomRs, and forever. You can use hoogle to search for their names and read more about them; in the future, you can also use it to search for functions you wish existed by their type.