現在我正在嘗試制作一個程式,給出迄今為止輸入的所有數字的總和。目前我有這個代碼的開頭:
import System.Exit
main :: IO()
main = do
a <- getLine
if a == "EXIT_PROGRAM"
then
exitWith ExitSuccess
else
print(a)
main
它現在作業正常,但你可能會說這不是我想要的。為此,我必須保存之前的總和,然后將其添加到 a,然后保存并重復該函式。我怎樣才能做到這一點?謝謝你。
uj5u.com熱心網友回復:
找到了辦法,應該早點想出來。我做了一個單獨的函式,它不像 main 可以接受輸入。然后我把產品喂進去了。
import System.Exit
multiplier :: Integer -> IO()
multiplier prevProduct = do
a <- getLine
if a == "EXIT_PROGRAM"
then
exitWith ExitSuccess
else
return()
let b = (read a :: Integer) * prevProduct
print(b)
multiplier b
main :: IO()
main = do
multiplier 1
我也改變了它,所以它成倍增加而不是相加
uj5u.com熱心網友回復:
另一個答案中建議的實作具有正確的行為,但讓我覺得可能并不完全地道。使用exitWith讓我印象深刻的是使用例外進行流控制 - 大多數語言(不僅僅是 Haskell)都不贊成這種技術。
這也導致需要使用return ()forelse分支才能什么都不做。在這里,return ()幾乎就像continue在 C# 這樣的語言中使用。
此外,該程式將無法處理任何錯誤輸入,例如foo、exit甚至EXIT PROGRAM。在所有這些情況下,它都會崩潰:
> multiplier 1
2
2
3
6
EXIT PROGRAM
*** Exception: Prelude.read: no parse
正如chi在評論中所建議的那樣,使用遞回會更慣用,但在 Haskell 中,您通常通過有一個干凈退出的基本案例來做到這一點。
所需的行為幾乎是Read Eval Print Loop (REPL),只是預先給出了評估函式。所以也許,readPrintLoop可能是一個合適的名字。這是一種方法:
readPrintLoop :: (Show a, Read b) => (a -> b -> a) -> a -> IO ()
readPrintLoop eval acc = do
s <- getLine
let m = readMaybe s
case m of
Just x -> do
let y = eval acc x
print y
readPrintLoop eval y
Nothing -> return ()
此操作使用readMaybe fromText.Read來決議輸入,并選擇優雅地失敗。因此,任何未決議的輸入(例如foo、exit或EXIT_PROGRAM)都將退出回圈。
它首先使用 讀取輸入getLine,使用 決議readMaybe,然后對Maybe值進行模式匹配m。
如果m是Nothing,則操作干凈地退出()。
如果m是一個Just值,它使用eval(函式引數)計算新的累加值,列印它,并使用新的累加器遞回。
由于 OP 描述了累積總和,并且來自同一用戶的答案累積了一個產品,因此我readPrintLoop通過允許呼叫者定義正在使用的函式來實作靈活性。
您甚至可以使用它來累積十進制數(因為任何Read實體都可以):
> readPrintLoop ( ) 0.0
1.1
1.1
2.3
3.4
exit
>
另一方面,如果你想main累積一個整數乘積,你可以這樣定義它:
main :: IO ()
main = do
readPrintLoop (*) 1
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/474050.html
上一篇:如何使用折疊對樹元素求和?
