Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with "Looping" IO in Haskell

Tags:

haskell

I'm new to Haskell, so I'm trying to make a simple two player text based game in order to help me learn it.

However, I've come across the problem of performing IO in a "loop". As far as I am aware, variables that are set from user input cannot be used unless they are set inside main. This is a problem because a recursive call to main is useless to me since main does not take any arguments. Ideally, I would have a function called from main that calls itself until one player loses. But, this does not seem to work, since using any variables set in that function by user input results in type errors.

The structure of the program is as follows:

*Prompt player 1 for name and set player1 variable.

*Prompt player 2 for name and set player2 variable.

*The "loop": Alternate between each player, prompting for commands until one player loses.

What would be the best way to go about tackling this problem?

like image 989
daedalic Avatar asked Jul 22 '11 04:07

daedalic


2 Answers

Ideally, I would have a function called from main that calls itself until one player loses. But, this does not seem to work, since using any variables set in that function by user input results in type errors.

This is entirely possible. Next time please include some code so we can help you through your misunderstanding. here is an example code snippet:

import System.IO

To handle buffering issues.

main = do
    hSetBuffering stdin NoBuffering
    putStrLn "Gimma a name ye skervy dog!"
    name1 <- getLine
    putStrLn "Good, Good, now another, and make it snappy!"
    name2 <- getLine
    loop name1 name2 10

Notice main can call another function (loop) that lives in the IO monad. This other function is perfectly capable of getting and acting on user input, calling itself, and/or taking arguments.

loop :: String -> String -> Int -> IO ()
loop _ _ 0 = return ()
loop n1 n2 i = do
    putStrLn $ "Ok Mr. " ++ n1 ++ " and Mrs. " ++ n2 ++
               " tis time to roll the dice!"
    print i
    putStrLn "Options: (k)eep looping, (i)ncrement loop counter by 10"
    c <- getChar
    putStr "\n"
    case c of
        'k' -> loop n1 n2 (i-1)
        _   -> putStrLn "Blood and bloody ashes, we have to keep going?" >>
               loop n1 n2 (i+10)

And loop just does a simple-stupid job of asking for a binary input (increment the counter or not) and, well, loops.

If this doesn't help then perhaps you can post a bit more complete question and code. I'll edit with an updated answer.

like image 110
Thomas M. DuBuisson Avatar answered Oct 06 '22 12:10

Thomas M. DuBuisson


Or you could use forever.

main = do
  x <- getLine
  foo
  forever $ do
     y <- getLine
     baz

If you're new to Haskell, I suggest you go through LYAH for a good introduction.

like image 32
sanjoyd Avatar answered Oct 06 '22 14:10

sanjoyd