Abstract3000
Abstract3000

Reputation: 79

Haskell replace space with Char

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

Answers (5)

Shanthakumar
Shanthakumar

Reputation: 768

import Data.List
newLine :: String -> String
newLine  = intercalate "%50" . words 

Upvotes: 0

viorior
viorior

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

chi
chi

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

leftaroundabout
leftaroundabout

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

mhwombat
mhwombat

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

Related Questions