Haskell中的递归 - 从键盘读取的数字总和

时间:2017-02-27 00:21:00

标签: haskell recursion

我正在尝试从键盘读取的总数但是我没有得到它,在函数sumNums例如我把7和我可以输入8个数字但只需要添加7,我想要输入7并添加7。在主要功能中,我不能使用sumNums

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 个答案:

答案 0 :(得分: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]

最后,您可以将sum提升到IO monad以添加数字。

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

因此,您可以简单地将sumNums写为

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

更简单地说,replicateMsequencereplicate结合在一起(实际上是replicateM = (sequence . ) . replicate)。

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