Tutorial :How to print a list of strings using 'unwords' in Haskell?



Question:

I want to print list of strings like shown below.

|Name|Country|Age|  ------------------  |1   |USA    |20 |  |2   |UK     |19 |  

I was able to achieve this using the following.

printfieldName :: [String] -> String  printfieldName [] = []  printfieldName (x:xs)  = "|" ++ x ++ "\t" ++ printfieldName (xs)  

Is it possible to achieve this using the inbuilt function 'unwords'. I was able print it using 'unwords' but was unable to place | between the words.


Solution:1

I see there is a additional space between '|' and word, so you can use this function:

printfieldName x = unwords (map ((++) "|") x)  ++ "|"  

little explanation:

(++) "|" - creates a function which take prefixes each word with "|", so  (++) "|" "test" -> "|test"   

then, map applies this function to a list of words converting it to ["|1", "|USA", "|20", ... ]

then unwords joins them into a string with spaces between words. The ++ "|" is needed to add final |


Solution:2

Firstly, I would write it like this:

printfieldName []     = []  printfieldName (x:xs) = "|" ++ x ++ "\t" ++ printfieldName xs  

Well, actually, no, like this:

concatMap (\x -> '|' : x ++ "\t")  

Well, maybe more like:

concatMap (printf "|%s\t")  

OK. So can it be done as 'unwords'?

-- | 'unwords' is an inverse operation to 'words'.  -- It joins words with separating spaces.  unwords                 :: [String] -> String  unwords []              =  ""  unwords ws              =  foldr1 (\w s -> w ++ ' ':s) ws  

No. But see if you can write concatMap as a foldr...


Solution:3

Data.List has a function called intersperse. Perhaps you can use that.

printfieldName xs = "|" ++ unwords (intersperse "|\t" xs) ++ "|"  


Solution:4

Perhaps a little over the top from what you asked, but:

formatTable :: [String] -> [[String]] -> String  formatTable header rows =      formatRow header ++ dashRow ++ concatMap formatRow rows        where formatRow cells = bracket '|' (spread cells)            dashRow         = bracket '+' (map (\n -> replicate n '-') widths)            bracket c cells = concatMap (c:) cells ++ (c:"\n")              spread cells    = zipWith pad widths cells            pad n s         = take n (s ++ repeat ' ')              widths = foldr maxLengths (repeat 0) (header : rows)            maxLengths = zipWith (\c l -> max (length c) l)  

Then, for example:

> let h = words "Name Country Age"  > let rows = map words ["1 USA 20", "2 UK 19"]  > h  ["Name","Country","Age"]  > rows  [["1","USA","20"],["2","UK","19"]]  > putStr $ formatTable h rows  |Name|Country|Age|  +----+-------+---+  |1   |USA    |20 |  |2   |UK     |19 |  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »