通过 Graham Hutton 的Haskell 编程(第二版),我刚刚成功解决了练习 10.5(第 138 页)。任务是编写一个函数
adder :: IO ()
读取 n
数字(以交互方式定义),对它们进行求和,然后打印结果,如下所示:
> adder
How many numbers? 3
5
4
6
The total is 15
函数
readInt
和 readLine
已给出:
readInt :: IO Int
readInt = do
line <- readLine
return (read line :: Int)
readLine :: IO String
readLine = do
c <- getChar
case c of
'\n' -> return []
_ -> do
cs <- readLine
return (c:cs)
所以我只需要编写
adder
函数:
adder :: IO ()
adder = do
putStr "How many numbers? "
n <- readInt
ns <- sequence [readInt | _ <- [1..n]]
sum <- sumUp ns
putStr $ "The total is " ++ (show sum) ++ "\n"
sumUp :: [Int] -> IO Int
sumUp xs = return $ foldl (+) 0 xs
我对我的解决方案几乎满意,但我只想内联
sumUp
函数。但是,我不知道该怎么做。
如何将
[a] -> IO a
函数内联到 do
块中?
这里不需要使用
return
,我们可以使用sum :: (Foldable f, Num a) => f a -> a
来对数字进行求和:
adder :: IO ()
adder = do
putStr "How many numbers? "
n <- readInt
ns <- sequence [readInt | _ <- [1 .. n]]
putStr $ "The total is " ++ (show (sum ns)) ++ "\n"
我们也可以重复
readInt
到replicateM :: Applicative m => Int -> m a -> m [a]
:
import Control.Monad(replicateM)
adder :: IO ()
adder = do
putStr "How many numbers? "
ns <- readInt >>= (`replicateM` readInt)
putStrLn $ "The total is " ++ (show (sum ns))
至于
readInt
,可以这样实现:
readInt :: IO Int
readInt = readLn