Those are my first explorations in Haskell, so pardon me if it should be obvious.
I have been playing all afternoon with Haskell, sifting through the tutorial 99 questions on HaskellWiki, using my own list type (typical Cons). I’ve added “obvious” functions as I went on, and I have tried to make them as concise as possible (employing point-free notation whenever possible)
The 12th problem is about decoding a run-length encoded list, that is:
> decode [Multiple 5 'a', Single 'b', Multiple 2 'c']
"aaaaabcc"
And I thought about using map to decode each element, then concat the result (thanks Google on this), and finally remembered that I had seen something like concatMap in my readings, which GHCi quickly confirmed:
> :t map
map :: (a -> b) -> [a] -> [b]
> :t concat
concat :: [[a]] -> [a]
> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]
It looked like it would be obvious to reimplement concatMap:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap = concat . map
Except that GHCi quite complains:
List.hs:110:15:
Couldn't match expected type `[a] -> [b]'
with actual type `[a0]'
Expected type: [[a0]] -> [a] -> [b]
Actual type: [[a0]] -> [[a0]]
In the first argument of `(.)', namely `concat'
In the expression: concat . map
I could not figure it out, so I looked up on the web, and the definition referenced in Prelude is actually:
concatMap f = concat . map f
And I don’t quite understand why this f is necessary, since it’s type is obviously a -> [b] as specified by the signature…
So why is f necessary here ?
Starting with the standard definition,
Your first definition gives you:
which doesn’t type check because
(map f) :: [a] -> [b], whileconcattakes[[a]], a list of lists.Note the particular error message shown in the question doesn’t describe the above type-check failure. The given message arises from declaring the return type
concatMapas[a] -> [b], which isn’t reconcilable with[a0], the return type ofconcat. If you leave off the type signature, the response is:Here, the type error occurs when reconciling the return type of
mapwith the argument type ofconcat. It turns out this case is more useful for debugging as it contains a hint why the type check failed.