1

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

我有一个[[[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

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

4

3 回答 3

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
于 2013-06-30T10:31:14.583 回答
2

让我们从类型开始。你所拥有的是[[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"]]

然后,您可以寻求使其更通用并相应地对其进行重构。

于 2013-06-30T10:55:21.483 回答
0

请记住,mapM_ 采用一个返回单子操作的函数作为其参数。该动作可以使用正常的一元操作组成。

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

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

而您希望拥有:

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

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

于 2013-07-01T11:41:23.950 回答