Reputation: 31
I asked a question earlier and was left with more questions than answers.
I want to be able to do the following:Enter number of integers in a list followed by the number list.
Examples
4 1 2 3 4
OR
8 1 2 3 4 5 6 7 8
Right now I have the following code that is not working.
import Control.Monad
readLn = do
putStrLn "Enter how many numbers:" -- clearer
num<-getLine
numbers<- replicateM num action
putStrLn("Enter a number: ")
numberString <- getLine
return (read numberString :: Int)
-- here we have numbers :: [Int]
Upvotes: 0
Views: 448
Reputation: 532418
If you want a single line of input, it doesn't need to include the number of numbers, because you'll just split the line on whitespace to get your list.
foo :: IO [Int]
foo = do
putStr "Enter your numbers, separated by whitespace (e.g. 4 5 3 2): "
line <- getLine
return $ map read (words line)
words
splits an input like 2 3 4 5
into the list ["2", "3", "4", "5"]
.
If you want to control how many numbers are entered, with a separate prompt for each number, then you need replicateM
:
-- No error handling or line editing, for simplicity
foo' :: IO [Int]
foo' = do
putStr "How many numbers?: "
n <- readLn
replicateM n $ do
putStr "Enter a number: "
readLn
readLn
is equivalent to fmap read getLine
; you get a line of input, calling read
on the resulting string.
replicateM
takes an IO
action, defined by the nested do
block, as its second argument. You were passing an undefined variable action
. That action produces an IO Int
value, which replicateM
repeats n
times an combines the resulting IO Int
values into a single IO [Int]
value. (Which is the difference between replicateM
and replicate
, which would have produced a list of actions, [IO Int]
.)
Because foo
and foo'
are both declared to have type IO [Int]
, the compiler can infer the proper specific types for the uses of read
and readLn
.
Upvotes: 1