Haskell打印[[[Char]]]到IO

时间:2013-06-30 10:08:02

标签: haskell io system.printing

嗨我使用IO打印[[[Char]]]时遇到小问题。

我有一个[[[Char]]]列表 - 换言之[[String]]

我想像

一样打印它们
FirstStringOfFirstListOfStrings
SecondStringOfFirstListOfStrings
.
.
.
LastStringOffFirstListofStrings
(some gap anything empty line "----" string anything)
FirstStringOfSecondsListOfStrings

换句话说,我不希望[String]一个在另一个下打印(例如,至少一行中断,或者某行填充------

mapM_ (mapM_ print) 

我的想法是将(mapM_ print)函数与另一个函数组合起来,但这似乎不起作用。有什么建议?

编辑:这是一个例子,按要求

要打印的数据:[["abc","cde","efg"],["hjk","mno","prs"],["stu","wxy","zzz"]]

在使用mapM_ (mapM_ print)时,它会打印出

abc
cde
efg
hjk
mno
prs
stu
wxy
zzz

但我希望它像这样打印:

abc
cde
efg

hjk
mno
prs

stu
why
zzz

它们可以用空行或一些字符串分隔。

3 个答案:

答案 0 :(得分:3)

让我们从类型开始。你拥有的是[[String]],你想要的是[[IO ()]],即每个String被转换为IO ()动作(打印它)。让我们尝试实现这个目标:

strToPrint :: [[String]] -> [[IO ()]]
strToPrint strs = map (map putStrLn) strs                

现在我们希望[[IO ()]]变平以获得[IO ()],同时我们插入所需的换行符打印操作,同时展平列表。

flattenActions :: [[IO ()]] -> [IO ()]
flattenActions actions = concat $ intersperse [(putStrLn "")]  actions

现在,我们可以使用[IO ()]逐个执行这些sequence_操作。似乎我们可以使用功能组合将所有这些功能组合成一个功能,因此我们得到了

printStrings :: [[String]] -> IO ()
printStrings  = sequence_ . flattenActions . strToPrint

并使用它:

main = printStrings [["a","b","c"],["d","e","f"]]

然后,您可以寻找使其更通用并相应地重构它。

答案 1 :(得分:2)

使用您的示例代码,对于任何分隔符' sep'那么:

import Data.List (intercalate)

let x = [["abc","cde","efg"],["hjk","mno","prs"],["stu","wxy","zzz"]]

p sep = putStr . unlines . intercalate sep

main = do
    p "" x
    p "---" x

答案 2 :(得分:0)

请记住,mapM_采用一个返回monadic动作作为参数的函数。那个动作可以 使用正常的monadic操作组成。

因此,在您的代码示例中,您有:

printStrings :: [[String]] -> IO ()
printStrings = mapM_ (mapM_ putStrLn)

您希望:

printStrings :: [[String]] -> IO ()
printStrings = mapM_ (\xs -> (mapM_ putStrLn) xs >> putStrLn ""))

所以我们要做的是用函数替换内部mapM_ putStrLn:  \xs -> mapM_ (putStrLn xs >> putStrLn "")也打印出分隔符。