superlinux
superlinux

Reputation: 470

How to initialize a list of integers from stdin reading each integer on a separate line in haskell?

I am a newbie in Haskell but I know C++ and Java. now I wonder how can I read a list of integers similar to this psuedocode?

   cout << "Please enter the size of your list";
   cin >> list_size;
   int mylist[listsize];
   for (int i = 0 ; i<list_size; i++) {
      cout<< "please enter the next number:";
      cin>> number;
     mylist[i]=number;
    }

Upvotes: 2

Views: 432

Answers (1)

danidiaz
danidiaz

Reputation: 27766

The answers given in the linked question use lazy IO (through getContents).

Personally, I don't like lazy IO, and I think trying to understand how it works in combination with do-notation is a recipe for confusion. So here's an answer that doesn't use lazy IO:

import Control.Monad(replicateM)

main :: IO ()
main = do
    putStrLn "Please enter the size of your list"
    times <- readLn
    ns <- replicateM times 
                     (do putStrLn "please enter the next number: "
                         readLn :: IO Int) -- type annotation to remove ambiguity
    print ns

replicateM takes a number n and an effectful action, and returns a new action that executes the original n times and returns a list with the results.

What if I want to display a different prompt message for each number?

That can be understood as an effectful transformation on the list of prompt messages, one that substitutes each message by the value entered. A kind of "effectful map".

The function traverse can be used here. Or perhaps for, which is the flipped version of traverse:

{-# language ScopedTypeVariables #-}

import Data.Traversable (for)

main :: IO ()
main = do
    putStrLn "Please enter the size of your list"
    times :: Int <- readLn
    ns <- for [1..times]
              (\prompt -> do putStrLn ("enter " ++ show prompt)
                             readLn :: IO Int) -- type annotation to remove ambiguity
    print ns

The :: IO Int annotation is required in the example because readLn can read any type that has a Read instance, but we aren't doing anything Int-specific with the results, so we need to inform the compiler about the type somehow.

Upvotes: 13

Related Questions