题
基本上我需要做的是编写一个接受类型列表的函数 [(String, String)]
并逐行打印出内容,输出如下所示:
FirstString : SecondString
FirstString : SecondString
..等等,对于列表中的每个项目。我有以下代码并打印出来,但由于某种原因它打印出一行包含 [(),()]
在最后。
display :: Table -> IO ()
display zs = do {
xs <- sequence [putStrLn ( a ++ " = " ++ b) | (a, b) <- zs];
print xs
}
我做错了什么吗?
解决方案
最终打印xs是不必要的。这里的序列返回一堆()s(putStrLn的返回值),print也打印出来。
当你正在使用它时,现在print xs已经消失,你可以摆脱xs变量绑定,并将序列转换为sequence_以丢弃返回值,给出:
display :: Table -> IO()
display zs = sequence_ [putStrLn (a++" = "++b) | (a,b) <- zs]
其他提示
您甚至可以使用 mapM
:
display :: Table -> IO ()
display = mapM_ (\(a,b) -> putStrLn (a++" = "++b))
我同意 ja 的观点,您应该将代码分成两个函数:
- A 纯的 部分:一个函数,它获取您的数据结构并将其转换为字符串
- 一个 不纯的 部分,将该字符串呈现到控制台
这是一个简单的实现:
showTable :: Table -> String
showTable xs = concatMap format xs
where
format (a, b) = a ++ " : " ++ b ++ "\n"
display :: Table -> IO ()
display table = putStr (showTable table)
这种设计有两个优点:
其一,大部分“逻辑”都在代码的纯粹部分中,这很好,以函数式编程的方式。
其次,这只是简单的软件工程原理;如果您想在代码的另一部分格式化数据结构(似乎有可能),您现在拥有一个可以使用的可重用函数。
编写一个函数,将一个元组取一个字符串,格式化为你想要的 然后在你的列表上运行concatMap;打印结果。
不隶属于 StackOverflow