Well, this code won't compile. Let's tackle why it won't compile one issue at a time:
First off, in your punct function, this compilation error happens twice:
Foo.hs:7:11: error:
• Couldn't match expected type ‘(Char -> Bool) -> Bool’
with actual type ‘Char’
• The function ‘c’ is applied to one argument,
but its type ‘Char’ has none
In the expression: c isDigit
In a stmt of a pattern guard for
an equation for ‘punct’:
c isDigit
What the compiler is trying to tell you here is that you wrote "call c as a function, passing it the argument isDigit", when obviously you meant that the other way around. So first we swap those:
punct :: Char -> Bool
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True
| isDigit c = True
| isAlpha c = True
| otherwise = False
With that fixed, your first format function in fact compiles:
format1 :: String -> String
format1 s = intercalate "" [if (punct c) then (c:" ") else [c] | c <- s]
And it also seems to work as advertised:
*Foo> format1 "a.b_c"
"a . b _c "
Okay, now what about that second format function? Well, at first it won't compile:
Foo.hs:18:12: error:
• Couldn't match type ‘[Char] -> [[Char]]’ with ‘[Char]’
Expected type: String
Actual type: [Char] -> [[Char]]
• Probable cause: ‘map’ is applied to too few arguments
In the expression: map (\ c -> if punct c then (c : " ") else [c])
In an equation for ‘format’:
format s = map (\ c -> if punct c then (c : " ") else [c])
The compiler is telling you here (with the "Probable cause" message) that you forgot to use s on the right hand side, and should have written:
format s = map (\c -> if punct c then (c:" ") else [c] ) s
But event that won't compile: (but the error message is different now)
Foo.hs:18:12: error:
• Couldn't match type ‘[Char]’ with ‘Char’
Expected type: String
Actual type: [[Char]]
• In the expression:
map (\ c -> if punct c then (c : " ") else [c]) s
In an equation for ‘format’:
format s = map (\ c -> if punct c then (c : " ") else [c]) s
That's saying that your result should have been a String (that is, a list of Char, or [Char]), but instead was a list of Strings (that is, a [[Char]])
This is because you turned each character into a string, instead of into a character. One way to fix this is to turn each character into a character:
format s = map (\c -> if punct c then ' ' else c ) s
Another way is to apply intercalate "" (or concat) as you did before to join the list of strings into a single string:
format s = intercalate "" $ map (\c -> if punct c then " " else [c] ) s
c isDigit?