2017-08-23 74 views
5

我想通過編程一個簡單的數學學習程序來同時學習數學和Haskell。爲什麼程序流量控制是隨機執行的

它首先:

  1. 生成隨機數。
  2. 過濾這些數字可以創建一個簡單的問題。
  3. 顯示的問題,然後把我的答案
  4. 最後,它交給我的兩個答案與正確答案給另一個函數給我的反饋(「恭喜」 - 或 - 「對不起,正確的答案是空白。)

出於某種原因,祝賀函數結束後,它似乎隨機選擇的地方去下一個,或者:

  1. 它返回到(這是我期望它做)
  2. 或者隨機循環,它會立即進入數學測試功能。發生這種情況時,步驟2從上面不會發生,我開始在問題中得到小數。然後它可能會重複此步驟或返回主要

當試圖調試我只是不停的按RETURN問題,它會出現在不同的時間。我還添加了一些調試「打印」語句。

這是程序的3個功能。請注意,主要調用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 "" 

這是我的調試輸出。請注意,只有當暫停結束後,它纔會立即返回到主體。

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

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%" 

如果有幫助,這是遠程相關的是我迄今爲止發現的唯一的事情就是:Second of several forked processes does not run in Haskell

最後,如果這有助於制定您的答案,我就是Monad的入門級別。

我會很感激任何人可以提供什麼幫助,爲什麼它不是直接返回到主要暫停結束,爲什麼它會跳過分數過濾器。

謝謝^^

回答

7

funPercentOfNumberToAnother,你有這樣的條款:

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" 

你的目的是要回到函數的開始,並開始了,如果數字是醜陋的;或以其他方式繼續向用戶顯示號碼。這種情況一直髮揮作用,但問問自己......在這if條款的末尾會發生什麼?無論是then還是else完成執行,都不執行thenelse分支中的內容。

所以,當你得到一些醜陋的數字時,你開始一個遞歸調用,尋找更好的數字並顯示它們。然後,當遞歸調用完成時,無論如何,您繼續向用戶顯示原始的醜陋的數字!

這裏需要一個不同的控制流程,例如編寫一個總是返回非醜陋數字的函數,然後在您的(現在是非遞歸的)funPercentOfNumberToAnother函數中使用該函數。或者,您可以將功能的其餘部分(向用戶顯示數字的部分)拖到ifelse部分,以便您不要爲難看的數字執行此操作。

0

根據amalloy的很好的解釋,我明白髮生了什麼事情並修復了,然後測試了這個問題。在以下if語句之外的代碼:

if uglyAnswers 
    then funPercentOfNumberToAnother 
    else ... 

導致不好的答案,以便在遞歸停止時稍後停下來。所以基本上我在他們身上儲備。

也許這可以更好地解釋它。看到我在第一次嘗試時得到了一個清晰的答案,因此它不必經歷遞歸。對於第二個去有兩個電話,因爲第一個電話找到了答案分數:

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

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

1 
In the else statement 
=================================== 
Finally outside the else statement 
ofNum: 10 
isNum: 4 

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

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

1 
Bad answer alert! 
=================================== 
In the else statement 
=================================== 
Finally outside the else statement 
ofNum: 160 
isNum: 80 
=================================== 
Finally outside the else statement 
ofNum: 55 
isNum: 0.55 

這裏的可行代碼段從原來的問題:

funPercentOfNumberToAnother :: IO() 
funPercentOfNumberToAnother = do 
    (percentDec, percentStr) <- getPercent 
    ofNum <- getDecimal (200 :: Decimal) 
    let isNum = percentDec * ofNum 
    if uglyAnswers ([ofNum, isNum], [percentDec]) 
     then funPercentOfNumberToAnother 
     else do 
      let message = show isNum ++ " is what percent of " ++ show ofNum ++ "?\n" 
      testProblem (percentStr ++ "%", message) 


testProblem :: (String, String) -> IO() 
testProblem (correctAns, message) = do 
    putStrLn message 
    putStrLn "\n\n" 
    putStr "> " 
    myAns <- getLine 
    if myAns == correctAns 
     then putStrLn "Congratz!" 
     else do 
      putStrLn ("Sorry the correct answer is: " ++ show correctAns) 
    pause 
相關問題