我想显示任意类型列表的内容,每行一个元素,从 1 开始编号,如下所示:
字符串示例:
> bs "Hallo"
1. 'H'
2. 'a'
3. 'l'
4. 'l'
5. 'o'
整数示例
> bs [5,6,1,2]
1. 5
2. 6
3. 1
4. 2
元组示例
> bs [(4,"Test"),(3,"Aye"),(5,"Fives")]
1. (4,"Test")
2. (3,"Ayes")
3. (4,"Fives)
我发现这是一种解决方案:
bs' :: Show a => [a] -> Integer -> IO ()
bs' [] _ = return ()
bs' (x:xs) y = do
putStrLn $ (show y) ++ ". " ++ (show x)
bs' xs $ succ y
bs x = bs' x 1
我也这样做了,发现它更奇怪(但有点酷):
bs' :: Show a => [(Integer,a)] -> IO ()
bs' [] = return ()
bs' ((x1,x2):xs) = do
putStrLn $ (show x1) ++ ". " ++ (show x2)
bs' xs
bs x = bs' (zip [1..] x)
我已经完成了大约 25 年的命令式编程,并且对学习新东西非常感兴趣。同时,如果在 Haskell 中编写代码感到难以置信的“奇怪”,我仍然无法想象使用这种“来自月球的疯狂语言”如何完成一个大项目:)
编辑:我要感谢大家。我选择一个答案,因为我必须这样做,但所有答案都非常有帮助!我还想说,我拥有的最佳解决方案是因为“在真正的问题中”我不得不跳过一些列表元素,并且在使用 zip 方法时编号出错。阅读完所有答案后,我很确定,即使如此,解决方案还是首先过滤列表,然后压缩映射输出函数。
最佳答案
还有Text.Printf
,如果您怀旧 printf
:
import Text.Printf
bs :: Show a => [a] -> IO ()
bs = sequence_ . zipWith (\n x -> printf "%d. %s\n" n (show x)) [(1 :: Int)..]
或者如果您不想使用
printf
:bs xs = sequence_ $ zipWith (\n x -> mapM_ putStr [show n, ". ", show x, "\n"]) [1..] xs
这些都不是非常惯用的,我认为大多数人会创建一个返回字符串的纯函数,然后在必要时打印它:
bs' xs = unlines $ zipWith (\n x -> show n ++ ". " ++ show x) [1..] xs
bs xs = putStr (bs' xs)
关于haskell - Haskell 中的编号输出行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24824457/