2017-02-27 31 views
1

我試圖從鍵盤讀取的總和數字,但我不明白,在函數sumNums例如我把7和我可以輸入8個數字,但只是添加7 ,我想,輸入7並添加7.在主函數中我沒有得到使用sumNumsHaskell遞歸 - 從鍵盤讀數的總和

getInt :: IO Int 
getInt = do 
s <- getLine 
return (read s) 

sumNums :: Integer -> IO Int 
sumNums n = do 
    x<-getInt 
    if n==0 
    then return 0 
    else do 
     rest <- sumNums (n-1) 
     return (x+rest) 

main = do putStrLn "Type numbers: " 
suma <- sumNums 7 
putStrLn "Sum: " ++ show sum 
average <- suma/7 
putStrLn "Average: " ++ show average 
+1

嘗試以'n == 1'結尾;另外,您不能將'(/)'應用於'Integral'類型。嘗試用'fromIntegral'投射'suma'。 – ThreeFx

回答

3

主要的問題是,你看一個數字,然後檢查的n該值指示你應該讀另一個數字。相反,首先檢查n的值。

sumNums 0 = return 0 
sumNums n = do 
    rest <- sumNums (n - 1) 
    x <- getInt 
    return (x + rest) 

但是,您應儘量避免顯式遞歸。許多常見模式已經被抽象爲高階函數。

在這裏,你想要什麼?你想總結一個數字列表,你可以通過運行getInt幾次。與replicate功能開始重複getInt次所需數量:

> :t replicate 3 getInt 
replicate 3 getInt :: [IO Int] 

然後使用sequence所有整數解壓縮到一個單獨的列表。

> :t sequence (replicate 3 getInt) 
sequence (replicate 3 getInt) :: IO [Int] 

最後,可以解除sumIO單子加起來的數字。

> :t sum <$> sequence (replicate 3 getInt) 
sum <$> sequence (replicate 3 getInt) :: IO Int 

因此,你可以寫sumNums僅僅作爲

sumNums n = sum <$> sequence (replicate n getInt) 

更簡單地說,replicateM結合sequencereplicate(實際上,replicateM = (sequence .) . replicate)。

import Control.Monad 
sumNums n = sum <$> replicateM n getInt 
+0

我可能會更進一步:'sumNums n = sum <$> replicateM n getInt' – user2297560

+0

非常感謝,它的工作原理。 :D – Darkmantis

+0

@ user2297560的確,我忘記了'replicateM'。 – chepner