haskelliosystem.printing

Haskell printing [[[Char]]] to IO


Hi I have small problem with printing [[[Char]]] using IO.

I have a [[[Char]]] list - in another words [[String]]

I would like to print them like

FirstStringOfFirstListOfStrings
SecondStringOfFirstListOfStrings
.
.
.
LastStringOffFirstListofStrings
(some gap anything empty line "----" string anything)
FirstStringOfSecondsListOfStrings

In another words I don't want the [String] to be printed one under another (one row break at least or some line filled with ------ for example)

mapM_ (mapM_ print) 

My idea was to compose the (mapM_ print) function with another but that doesn't seem to work. Any suggestions?

Edit: Here's an example, as requested

data to print: [["abc","cde","efg"],["hjk","mno","prs"],["stu","wxy","zzz"]]

while using mapM_ (mapM_ print) it prints like

abc
cde
efg
hjk
mno
prs
stu
wxy
zzz

But I would like it to be printed like this:

abc
cde
efg

hjk
mno
prs

stu
why
zzz

They can be separated by an empty line or some string.


Solution

  • Lets start with types. What you have is [[String]] and what you want is [[IO ()]] i.e each String gets converted to a IO () action (to print it). Lets try to achieve this:

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

    Now we want [[IO ()]] to flatten to get [IO ()] where we insert the desired line break print action as well while flattening the list.

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

    Now we can execute these [IO ()] action one by one using sequence_. It seems we can combine all these functions into one function using functional composition and hence we get

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

    And use it like:

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

    You can then look for making this more generic and refactor it accordingly.