Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why program flow control executes randomly

Tags:

haskell

I'm trying to learn math and Haskell at the same time by programming a simple math learning program.

It starts by:

  1. Generating random numbers.
  2. Filters those numbers to create an easy problem to work with.
  3. Display the question then take my answer
  4. Lastly, it hands both my answer and the correct answer to another function to give me feedback (a "Congratulations" --or-- "Sorry, the correct answer is BLANK).

For some reason, after the congratulations function ends, it seems to randomly choose where it goes next, either:

  1. It returns to main (which is what I expect it to do).
  2. Or at random loops it'll go immediately to the math testing function. When this happens, step 2 from above doesn't occur and I start getting fractional numbers in the question. Then it may repeat this step or go back to main.

When trying to debug the problem I would just keep hitting RETURN and it would occur at different times. I've also added some debug 'print' statements.

Here's 3 functions from the program. Note that main calls funPercentOfNumberToAnother:

funPercentOfNumberToAnother :: IO ()
funPercentOfNumberToAnother = do
    (percentDec, percentStr) <- getPercent
    ofNum <- getDecimal (200 :: Decimal)
    let isNum = percentDec * ofNum
    if uglyAnswers ([ofNum, isNum], [percentDec])
        then do
            putStrLn ("ofNum: " ++ show ofNum)
            putStrLn ("isNum: " ++ show isNum)
            putStrLn "___________________________"
            funPercentOfNumberToAnother
        else do
            putStrLn ("ofNum: " ++ show ofNum)
            putStrLn ("isNum: " ++ show isNum)
            putStrLn "Percents"
    -- putStrLn "\n\n"
    putStrLn (show isNum ++ " is what percent of " ++ show ofNum ++ "?\n" )
    putStr "> "
    ans <- getLine
    submitStringAnswer (ans, percentStr ++ "%")

submitStringAnswer :: (String, String) -> IO ()
submitStringAnswer (myAns, correctAns) = do
    if myAns == correctAns
        then putStrLn "Congratz!"
        else do
            putStrLn ("Sorry the correct answer is: " ++ show correctAns)
    pause


pause :: IO ()
pause = do
    x <- getLine
    putStrLn ""

Here's my debug output. Notice that The only time it gives fractional numbers is after it doesn't return to main immediately after pause ends.

     __  __       _   _                          _   _         
    |  \/  | __ _| |_| |__   ___ _ __ ___   __ _| |_(_) ___ ___ 
    | |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
    | |  | | (_| | |_| | | |  __/ | | | | | (_| | |_| | (__\__ 
    |_|  |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/

1.) Learn Math
2.) Math Lookup
3.) Quit Excolo

1
ofNum: 35
isNum: 15.75
___________________________
ofNum: 120
isNum: 102
Percents
102 is what percent of 120?

> 
Sorry the correct answer is: "85%"


15.75 is what percent of 35?

> 
Sorry the correct answer is: "45%"



     __  __       _   _                          _   _         
    |  \/  | __ _| |_| |__   ___ _ __ ___   __ _| |_(_) ___ ___ 
    | |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
    | |  | | (_| | |_| | | |  __/ | | | | | (_| | |_| | (__\__ 
    |_|  |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/

1.) Learn Math
2.) Math Lookup
3.) Quit Excolo

1
ofNum: 80
isNum: 44
Percents
44 is what percent of 80?

> 
Sorry the correct answer is: "55%"



     __  __       _   _                          _   _         
    |  \/  | __ _| |_| |__   ___ _ __ ___   __ _| |_(_) ___ ___ 
    | |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
    | |  | | (_| | |_| | | |  __/ | | | | | (_| | |_| | (__\__ 
    |_|  |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/

1.) Learn Math
2.) Math Lookup
3.) Quit Excolo

1
ofNum: 15
isNum: 2.25
___________________________
ofNum: 60
isNum: 0.6
___________________________
ofNum: 40
isNum: 30
Percents
30 is what percent of 40?

> 
Sorry the correct answer is: "75%"


0.6 is what percent of 60?

> 
Sorry the correct answer is: "1%"


2.25 is what percent of 15?

> 
Sorry the correct answer is: "15%"

If it helps, the only thing that is remotely relevant that I've found so far is: Second of several forked processes does not run in Haskell .

Lastly, I'm right at the entry level of Monads if that helps formulate your answer.

I would appreciate any help anyone can give as to what's happening, id est, why it's not returning straight to main after pause ends, and why would it skip the fractional number filter.

Thanks ^^

like image 500
kit Avatar asked Aug 23 '17 21:08

kit


People also ask

Why do we need flow control in programming?

The control flow is the order in which the computer executes statements in a script. Code is run in order from the first line in the file to the last line, unless the computer runs across the (extremely frequent) structures that change the control flow, such as conditionals and loops.

What is program flow of control?

In computer science, control flow (or flow of control) is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. The emphasis on explicit control flow distinguishes an imperative programming language from a declarative programming language.

How can you regulate the flow of your programs execution?

Control structures allow you to regulate the flow of your program's execution. Using control structures, you can write Visual Basic code that makes decisions or that repeats actions. Other control structures let you guarantee disposal of a resource or run a series of statements on the same object reference.

Which statement causes the flow of program to change?

A programming language uses control statements to control the flow of execution of a program based on certain conditions. These are used to cause the flow of execution to advance and branch based on changes to the state of a program.


1 Answers

In funPercentOfNumberToAnother, you have this clause:

if uglyAnswers ([ofNum, isNum], [percentDec])
    then do
        putStrLn ("ofNum: " ++ show ofNum)
        putStrLn ("isNum: " ++ show isNum)
        putStrLn "___________________________"
        funPercentOfNumberToAnother
    else do
        putStrLn ("ofNum: " ++ show ofNum)
        putStrLn ("isNum: " ++ show isNum)
        putStrLn "Percents"

Your intent is to go back to the beginning of the function and start over, if the numbers are ugly; or otherwise continue with showing the numbers to the user. That works as far as it goes, but ask yourself...what happens at the end of this if clause? The stuff that is not in either the then or else branch is executed regardless, once either the then or else is done executing.

So, when you get some ugly numbers, you start a recursive call that looks for better numbers and displays them. Then when that recursive call is finished, you go on to show the user the original, ugly numbers anyway!

You will need a different control flow here, such as writing a function that always returns a non-ugly number, and then just using that in your (now non-recursive) funPercentOfNumberToAnother function. Or you could pull the rest of the function's body, the part that shows the numbers to the user, into the else part of the if, so that you don't do it for numbers that are ugly.

like image 156
amalloy Avatar answered Oct 07 '22 22:10

amalloy