Haskell:将辅助函数内联到do块中

lsmepo6l  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(79)

通过阅读Graham赫顿的《Haskell编程》(第二版),我成功地解决了练习10.5(第138页)。任务是编写一个函数adder :: IO (),它读取n数字(交互式定义),对它们求和,并打印结果,如下所示:

> adder
How many numbers? 3
5
4
6
The total is 15

函数readIntreadLine已经给出为:

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块中?

ugmeyewa

ugmeyewa1#

这里不需要用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

相关问题