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

lsmepo6l  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(173)

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

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

函数readIntreadLine已经给出为:

  1. readInt :: IO Int
  2. readInt = do
  3. line <- readLine
  4. return (read line :: Int)
  5. readLine :: IO String
  6. readLine = do
  7. c <- getChar
  8. case c of
  9. '\n' -> return []
  10. _ -> do
  11. cs <- readLine
  12. return (c:cs)

所以我只需要写adder函数:

  1. adder :: IO ()
  2. adder = do
  3. putStr "How many numbers? "
  4. n <- readInt
  5. ns <- sequence [readInt | _ <- [1..n]]
  6. sum <- sumUp ns
  7. putStr $ "The total is " ++ (show sum) ++ "\n"
  8. sumUp :: [Int] -> IO Int
  9. sumUp xs = return $ foldl (+) 0 xs

我几乎对我的解决方案很满意,但我只想内联sumUp函数。但是,我不知道该怎么做。
如何将[a] -> IO a函数内联到do块中?

ugmeyewa

ugmeyewa1#

这里不需要用return,我们可以用**sum :: (Foldable f, Num a) => f a -> a**来求和:

  1. adder :: IO ()
  2. adder = do
  3. putStr "How many numbers? "
  4. n <- readInt
  5. ns <- sequence [readInt | _ <- [1 .. n]]
  6. putStr $ "The total is " ++ (show (sum ns)) ++ "\n"

我们也可以重复readInt到**replicateM :: Applicative m => Int -> m a -> m [a]**:

  1. import Control.Monad(replicateM)
  2. adder :: IO ()
  3. adder = do
  4. putStr "How many numbers? "
  5. ns <- readInt >>= (`replicateM` readInt)
  6. putStrLn $ "The total is " ++ (show (sum ns))

对于readInt,这可以实现为:

  1. readInt :: IO Int
  2. readInt = readLn
展开查看全部

相关问题