Q:

Endless loop and a break for TUI in Haskell

I want to listen for keypresses and depending on those, use commands from System.Console.ANSI
package to manipulate console interface for my program.
In Python I would to this
while True:
    read_from_console()
    if condition:
        print_stuff_into_console
        break

How do I approach such task in Haskell, in simplest possible way?
Thanks

A:

The equivalent abstract pseudo-ish code in Haskell would look like:
loop = do
    line <- readFromConsole
    if condition line
        then do
            printStuffToConsole
            loop  -- Recurse - i.e. repeat the same thing again
        else 
            pure ()  -- Don't recurse - the function execution ends

 main = loop

But of course the devil would be in how readFromConsole and printStuffToConsole look. And these really depend on what exactly you'd like to do.
I will offer the dumbest possible implementation, just to illustrate how everything works and to build a complete program.
Let's say that "read from console" just means having the user enter a line of text and press Enter. For that, you can use the getLine function:
readFromConsole = getLine

And let's say you want to print the same thing every time. For printing, you can use the putStrLn function:
printStuffToConsole = putStrLn "Give me another!"

And then let's say that the condition for stopping is that the user enters "STOP". This can be expressed with a string comparison:
condition line = line /= "STOP"

If you put all of that together, you get a complete program:
loop = do
    line <- readFromConsole
    if condition line
        then do
            printStuffToConsole
            loop  -- Recurse - i.e. repeat the same thing again
        else 
            pure ()  -- Don't recurse - the function execution ends

    where
        readFromConsole = getLine
        printStuffToConsole = putStrLn "Give me another!"
        condition line = line /= "STOP"

 main = loop

Of course, while it's nice to have parts of the program semantically named, you don't strictly speaking have to do it if you wanted to make the whole thing shorter:
main = do
    line <- getLine
    if line /= "STOP"
        then do
            putStrLn "Give me another!"
            main
        else 
            pure ()

