Reputation: 79
I'm trying to come up with a function that will replace all the blank spaces in a string with "%50"
or similar and I know I'm messing up something with my types but can't seem to figure it out I have been trying the following (yes I have imported Data.Char
)
newLine :: String -> String
newLine xs = if x `elem` " " then "%50"
I also tried the if then else statement but really didn't know what to do with the else so figured just lowercase all the letters with
newLine xs = [if x `elem` ' ' then '%50' else toLower x | x<-xs]
would like the else statement to simply do nothing but have searched and found no way of doing that so i figured if everything was lowercase it wouldn't really matter just trying to get this to work.
Upvotes: 0
Views: 1747
Reputation: 768
import Data.List
newLine :: String -> String
newLine = intercalate "%50" . words
Upvotes: 0
Reputation: 1803
Try simple solution
newLine :: String -> String
newline "" = ""
newLine (' ':xs) = '%':'5':'0': newLine xs
newLine (x:xs) = x: newLine xs
or use library function
Upvotes: 3
Reputation: 116139
To replace characters with possibly longer strings, one can follow this approach:
-- replace single characters
replace :: Char -> String
replace ' ' = "%50"
replace '+' = "Hello"
replace c | isAlpha c = someStringFunctionOf c
replace _ = "DEFAULT"
-- extend to strings
replaceString :: String -> String
replaceString s = concat (map replace s)
The last line can also be written as
replaceString s = concatMap replace s
or even
replaceString s = s >>= replace
or even
replaceString = (>>= replace)
Upvotes: 0
Reputation: 120711
Well, the list comprehension is almost correct. Problem is:
"%50
" is not a valid character literal, so you can't have '%50'
. If you actually mean the three characters %
, 5
and 0
, it needs to be a String
instead.
' '
is a correct character literal, but the character x
can't be element of another char. You certainly mean simply x == ' '
.
Now that would suggest the solution
[if x == ' ' then "%50" else toLower x | x<-xs]
but this doesn't quite work because you're mixing strings ("%50"
) and single-characters in the same list. That can easily be fixed though, by "promoting" x
to a single-char string:
[if x == ' ' then "%50" else [toLower x] | x<-xs]
The result has then type [String]
, which can be "flattened" to a single string with the prelude concat
function.
concat [if x == ' ' then "%50" else [toLower x] | x<-xs]
An alternative way of writing this is
concatMap (\x -> if x == ' ' then "%50" else [toLower x]) xs
or – exactly the same with more general infix operators
xs >>= \x -> if x == ' ' then "%50" else [toLower x]
Upvotes: 0
Reputation: 8136
You're running into type mismatch issues. The approach you're currently using would work if you were replacing a Char
with another Char
. For example, to replace spaces with asterisks:
newLine xs = [if x == ' ' then '*' else toLower x | x<-xs]
Or if you wanted to replace both spaces and newlines with asterisks, you could use the elem
function. But note that the elem
function takes an array (or a String, which is the same as [Char]). In your example, you were trying to pass it a single element, ' '
. This should work:
newLine xs = [if x `elem` " \n" then '*' else toLower x | x<-xs]
However, you want to replace a Char
with a String
([Char]
). So you need a different approach. The solution suggested by viorior looks good to me.
Upvotes: 0