7

I'm new to Haskell and would be glad if someone would be willing to help me! I'm trying to get this program to work with a do while loop.

The result from the second getLine command gets put into the varible goGlenn and if goGlenn doesn't equal "start" then the program will return to the beginning

    start = do
    loop $ do lift performAction
        putStrLn "Hello, what is your name?"
        name <- getLine
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.") 
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
        putStrLn "Whenever you feel ready to begin please write Start"
        goGlenn <- getLine
        putStrLn goGlenn
    while (goGlenn /= "start")
Haskellnoob
  • 71
  • 1
  • 1
  • 2
  • To add to @chi's answer, the code you've written is more-or-less correct Haskell syntax, but things like `loop` and `while` aren't built in. Haskell doesn't actually have do-while loops, it has recursion that you can use to implement do-while loops. Haskell doesn't actually have loops at all, just recursion, you'll have to learn how to re-implement features from imperative languages that you're used instead. – bheklilr Feb 25 '16 at 22:35
  • @bheklilr I guess gallais is right in their comment below, though: the above code seems to be adapted from the `Control.Monad.LoopWhile` docs. – chi Feb 25 '16 at 22:39

2 Answers2

14

In Haskell you write "loops" recursively, most of the times.

import Control.Monad

-- ....

start = do
    putStrLn "Before the loop!"
    -- we define "loop" as a recursive IO action
    let loop = do
            putStrLn "Hello, what is your name?"
            name <- getLine
            putStrLn $ "Welcome to our personality test " ++ name 
                     ++ ", inspired by the Big Five Theory."
            putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
            putStrLn "Whenever you feel ready to begin please write Start"
            goGlenn <- getLine
            putStrLn goGlenn
            -- if we did not finish, start another loop
            when (goGlenn /= "start") loop
    loop  -- start the first iteration 
    putStrLn "After the loop!"
chi
  • 111,837
  • 3
  • 133
  • 218
  • 2
    I'm guessing OP is trying to use [`loop-while`](http://hackage.haskell.org/package/loop-while-1.0.0/docs/Control-Monad-LoopWhile.html) (see the similarity with the code excerpts). Seeing the list of imports would help. – gallais Feb 25 '16 at 22:34
  • @gallais Interesting, I did not know of that... Still, I wonder if the OP really wants to use that library, or just wants to achieve the same effect. For a beginner, I'd suggest to learn the basic way first. – chi Feb 25 '16 at 22:37
  • 2
    Instead of writing `let loop = ...; loop`, I like to write `fix $ \loop -> ...`. Of course this is purely stylistic. – user2407038 Feb 26 '16 at 00:00
3

Not sure, maybe this version can helps you:

import Control.Monad

loop action = do
    condition <- action
    when condition (loop action)

while = return

start =
    let action = do {
        putStrLn "Hello, what is your name?";
        name <- getLine;
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
        putStrLn "Whenever you feel ready to begin please write Start";
        goGlenn <- getLine;
        putStrLn goGlenn;
        while (goGlenn /= "start");
    }
    in loop action

(Edit) or can be too:

start =
    loop (do {
        putStrLn "Hello, what is your name?";
        name <- getLine;
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
        putStrLn "Whenever you feel ready to begin please write Start";
        goGlenn <- getLine;
        putStrLn goGlenn;
        while (goGlenn /= "start");
    })        
Ivan David
  • 348
  • 2
  • 5
  • If we define a custom helper function `loop`, I'd be temped to inline the definition of `action` and directly write `loop $ do ...`. – chi Feb 26 '16 at 08:39
  • but there is no problem... (i think so) please check edit in the answer – Ivan David Feb 26 '16 at 18:30
  • Yes, both ways are correct. The second one is nicer, at least for me. – chi Feb 26 '16 at 19:17