嗨我使用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
它们可以用空行或一些字符串分隔。
答案 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 "")
也打印出分隔符。