ben*_*ris 1 io recursion haskell
我正在尝试编写一个从用户读取整数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))
Run Code Online (Sandbox Code Playgroud)
目前它没有编译,错误说:
Couldn't match expected type `Int' with actual type `IO ()'
In the return type of a call of `addNumbers2'
In the second argument of `(+)', namely `addNumbers2 (num - 1)'
In the first argument of `print', namely
`(n + addNumbers2 (num - 1))'
Run Code Online (Sandbox Code Playgroud)
IO真的让我感到困惑,我正在尝试获得以下输出:
Enter a number:
3
Enter a number:
2
Enter a number:
1
Enter a number:
5
Sum is: 8
Run Code Online (Sandbox Code Playgroud)
你把addNumbers它看作是一个普通的函数,但它是一个IO操作,所以我们只能从里面do和里面得到它的数字answer <- addNumbers2,但是在它没有返回任何东西时,它只是打印它.
我重构了一点:
addNumbers :: IO ()
addNumbers = do
putStrLn "Enter how many numbers:" -- clearer
num <- getInt
sum <- addNumbers2 num -- use new version to return sum
print sum -- print them here
Run Code Online (Sandbox Code Playgroud)
现在addNumbers2实际上添加它们并返回它们:
addNumbers2 :: Int -> IO Int
addNumbers2 num = do
putStrLn "Enter a number:"
n <- getInt
if num == 1 then
return n -- pass the number back
else do
therest <- addNumbers2 (num - 1) -- get the rest of them
return (n + therest) -- add them up
Run Code Online (Sandbox Code Playgroud)
这样可行:
addNumbers
Enter how many numbers:
3
Enter a number:
1
Enter a number:
2
Enter a number:
3
6
Run Code Online (Sandbox Code Playgroud)
sequence :: Monad m => [m a] -> m [a]获取操作列表并运行它们,返回结果列表.如果我们只是列出一个或更多的getInts 列表[getInt| _<-[1..num]],replicate num getInt我们就可以做到numbers <- sequence (replicate num getInt).有一个简写Control.Monad,称为replicateM :: Monad m => Int -> m a -> m [a]
尽管如此,这样做会更好:
import Control.Monad
addNumbers' = do
putStrLn "Enter how many numbers:"
num <- getInt
numbers <- replicateM num (putStrLn "Enter a number" >> getInt)
print (sum numbers)
Run Code Online (Sandbox Code Playgroud)
这使
Enter how many numbers:
3
Enter a number
10
Enter a number
20
Enter a number
30
60
Run Code Online (Sandbox Code Playgroud)