I just started learning Haskell at uni, and while playing around with it, I stumbled upon a problem that I can't seem to grasp. The following code gives me the desired result:
import Data.List
list = ["Hello", "world"]
main = print $ intercalate " something " (reverse (map reverse list))
Output:
"dlrow something olleH"
But I want to write the 'main' function with dots instead of brackets, so it tried:
main = print $ intercalate " something " . reverse . map reverse list
However, this gives me the following errors:
test.hs:5:54: error:
• Couldn't match expected type ‘a0 -> [[Char]]’
with actual type ‘[[Char]]’
• Possible cause: ‘map’ is applied to too many arguments
I thought that these dots meant exactly the same as the brackets: function composition. Why do the brackets work, whereas the dots give me a type-related error? Any help would be greatly appreciated!
Brackets don't mean function composition. They just mean “group this subexpression”. Of course you can use them to make a chain of function compositions: the following defines c
as a composition of the functions f
, g
and h
c x = f (g (h x))
This could also be written as:
c = f . g . h
Thus, you could write
main = print $ c list
where c = intercalate " something " . reverse . map reverse
But if you then inline c
again, you need to be careful not to mess up the parsing rules: just writing list
to the right of that composition chain will not do, because function application binds more tightly than any infix operator (including .
, though that is in fact the tightest infix operator). I.e.,
intercalate " something " . reverse . map reverse list
is actually parsed as
(intercalate " something ") . (reverse) . (map reverse list)
But that's not what you wanted. You need to make sure that list
is actually the argument to the entire composition chain, not just its last element; the preferred way to do that is with the $
operator:
intercalate " something " . reverse . map reverse $ list
$
has the lowest prevedence, thus this is parsed as
((intercalate " something ") . (reverse) . (map reverse)) (list)
Alternatively, you can apply map reverse
to list
right away – this by itself isn't wrong, just the result isn't part of the composition chain anymore:
intercalate " something " . reverse $ map reverse list