2009-05-05 30 views
4

基本上我需要做的是编写一个函数,它需要一个类型为[(String, String)]的列表并打印出内容,以便逐行输出看起来像这:Haskell:打印出元组列表的内容

FirstString : SecondString 

FirstString : SecondString 

..等,列表中的每个项目。我得到了以下代码并将其打印出来,但出于某种原因,它最后打印出包含[(),()]的行。

display :: Table -> IO() 
display zs = do { 
    xs <- sequence [putStrLn (a ++ " = " ++ b) | (a, b) <- zs]; 
    print xs 
} 

有什么我做错了吗?

回答

10

最终打印xs是不必要的。这里的序列返回一堆()s(putStrLn的返回值),并且print也将其打印出来。

当你在这,现在打印XS走了,你可以摆脱XS变量绑定,并使序列到sequence_扔掉的返回值,赠送:

display :: Table -> IO() 
display zs = sequence_ [putStrLn (a++" = "++b) | (a,b) <- zs] 
+2

如果内存是一个问题,你可能想要检查newacct的方法(下面)。 – 2009-06-02 04:47:10

4

写一个将元组转换为字符串的函数,可以根据需要进行格式化。
然后concatMap函数在你的列表上;打印结果。

8

你甚至可以使用mapM

display :: Table -> IO() 
display = mapM_ (\(a,b) -> putStrLn (a++" = "++b)) 
+1

该方法使用的内存少于bdonlan的方法。在我的样本数据上,这个方法使用了大约70k。我不知道bdonlan的方法是否使用了更多的内存,因为它必须创建一个IO操作列表。 – 2009-06-02 04:40:44

+1

你如何测量内存使用? Haskell创建一个/ lot /短暂的分配,所以它可能意味着这只是简单的更快:) – bdonlan 2009-06-02 17:17:34

6

我将与JA同意,你应该在拆分您的代码以两个功能:

  • 一个部分:一个函数,你的数据结构并将它变成一个字符串
  • 一个不纯部分,表示将该字符串呈现给控制台

这里有一个简单的实现:

showTable :: Table -> String 
showTable xs = concatMap format xs 
    where 
    format (a, b) = a ++ " : " ++ b ++ "\n" 

display :: Table -> IO() 
display table = putStr (showTable table) 

这种设计有两个好处:

原因之一,大部分的'逻辑”是在代码中的沧海一粟,这是很好的,在一种功能性编程方式中。其次,这只是简单的软件工程原理;你现在有一个可以使用的可重用函数,如果你想要在你的代码的另一部分格式化你的数据结构(看起来很可能)。