Haskell IO从用户读取一个整数n,然后将n个整数相加

Haskell IO从用户读取一个整数n,然后将n个整数相加,haskell,recursion,io,Haskell,Recursion,Io,我试图编写一个程序,从用户那里读取一个整数n,然后读取n个整数(在单独的行上),最后显示读取的n个数字的总和 以下是我目前的代码: addNumbers :: IO () addNumbers = do putStrLn "Enter a number:" num <- getInt addNumbers2 num addNumbers2 :: Int -> IO () addNumbers2 num = do putStrLn "Enter a n

我试图编写一个程序,从用户那里读取一个整数n,然后读取n个整数(在单独的行上),最后显示读取的n个数字的总和

以下是我目前的代码:

addNumbers :: IO ()
addNumbers = do
    putStrLn "Enter a number:"
    num <- getInt
    addNumbers2 num

addNumbers2 :: Int -> IO ()
addNumbers2 num = do
    putStrLn "Enter a number:"
    n <- getInt
    if num == 1 then
        print n
    else do
        print (n + addNumbers2 (num - 1))
IO真的让我很困惑,我试图获得以下输出:

Enter a number:
3
Enter a number:
2
Enter a number:
1
Enter a number:
5
Sum is: 8

您将
addNumbers
视为一个普通函数,但它是一个IO操作,因此我们只能在
do
中从中获取数字,并使用
answer[ma]->m[a]
获取操作列表并运行所有操作,返回结果列表。如果我们只是制作一个满是
getInt
s的列表,
[getInt|up>您将
addNumbers
视为一个普通函数,但它是一个IO操作,因此我们只能在
do
内部和
answer[ma]>m[a]中从中获取数字
获取一个操作列表并运行所有操作,返回结果列表。如果我们只是让列表充满
getInt
s,
[getInt|up>您可以(也应该)使用可用的组合器

addNumbers2 n = do
    n_numbers <- replicateM n (putStrLn "Number, please: " >> getInt)
    let result = sum n_numbers
    return result

所以我们有一个IO操作,它请求输入并读取它

现在,我们可以使用

replicateM :: Int -> IO a -> IO [a]
由于我们传递了一个返回
Int
的IO操作,我们得到了一个
Int
列表

numbers <- replicateM n (putStrLn "Number?" >> getInt)
您可以(也应该)使用可用的组合器

addNumbers2 n = do
    n_numbers <- replicateM n (putStrLn "Number, please: " >> getInt)
    let result = sum n_numbers
    return result

所以我们有一个IO操作,它请求输入并读取它

现在,我们可以使用

replicateM :: Int -> IO a -> IO [a]
由于我们传递了一个返回
Int
的IO操作,我们得到了一个
Int
列表

numbers <- replicateM n (putStrLn "Number?" >> getInt)

与公认的解决方案相比,以下基于
管道的解决方案有一个微小的优势,即它不会在大量行上堆叠溢出:

import Pipes
import qualified Pipes.Prelude as Pipes

main = do
    numLines <- readLn
    total    <- Pipes.sum (Pipes.replicateM numLines readLn)
    print total
导入管道
导入合格管道。作为管道的前奏曲
main=do

numLines以下基于
管道的解决方案与公认的解决方案相比有一个微小的优势,即它不会在大量行上堆叠溢出:

import Pipes
import qualified Pipes.Prelude as Pipes

main = do
    numLines <- readLn
    total    <- Pipes.sum (Pipes.replicateM numLines readLn)
    print total
导入管道
导入合格管道。作为管道的前奏曲
main=do

numLines谢谢你,这是一个非常好的方法!@benharris现在有一个更整洁的方法了。@AndrewC比我快了一分钟…啊!!@AndrewC一点都不坏…我只是想:应该有人告诉这个家伙关于replicateM的事。如果我知道你要这么做,我可以节省一些时间。谢谢你,这是一个r这真是一个好办法!@benharris现在有一个更干净的办法了。@AndrewC比我快了一分钟……啊!!@AndrewC一点也不坏……我只是想:应该有人真的告诉这家伙关于replicateM的事。如果我知道你要做,我就可以节省一些时间。这确实是一个很好的方法。我我衷心地同意这个伟大的答案!这当然是一个非常好的方法。我衷心地同意这个伟大的答案!我试图理解你的代码,但看不出输入字符串何时转换为数值,可以求和。@epsilonhalbe
readLn
进行转换。这相当于
fmap read getLine
。我试图理解您的代码,但看不到输入字符串何时转换为可以求和的数字。@epsilonhalbe
readLn
进行转换。这相当于
fmap read getLine
 (putStrLn "Number?" >> getInt) :: IO Int
replicateM :: Int -> IO a -> IO [a]
numbers <- replicateM n (putStrLn "Number?" >> getInt)
replicateM n (putStrLn "Number?" >> getInt) >>= putStrLn . show . sum
import Pipes
import qualified Pipes.Prelude as Pipes

main = do
    numLines <- readLn
    total    <- Pipes.sum (Pipes.replicateM numLines readLn)
    print total
$ ./example
3<Enter>
10<Enter>
20<Enter>
30<Enter>
60