I've just spent some time working on a problem for which I needed to translate a list of lists a certain way. After successfully working through it I came up with this solution:
translate :: [[a]] -> [[a]]
translate ([]:xss) = []
translate xss = (map head xss) : (translate $ map tail xss)
Very shortly afterwards, i realized that I was simply trying to transpose a matrix... I thought "I probably lost a lot of time trying to do this, as surely Haskell has a function in its standard libraries to do such a common operation." So I decided to check, and unsurprisingly I found that the Data.List module includes a transpose function.
But what was actually surprising to me was the way it was defined:
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([] : xss) = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])
It uses list comprehensions instead of head and tail, which I thought was interesting but could not figure out why it did so.
Is there a reason why it is better to use list comprehension instead of the pre-defined head and tail functions (with map), the way that I did with my function? Is it something to do with the efficiency of the code?
I am not necessarily new to Haskell, but I am not an expert either. That being said, more technical answers and explanations would also be greatly appreciated as I am hoping to learn more about the intricacies of the language going forward (and even if I don't understand the reason now I will know what I have to research).