4

I'm trying to replace a string with another string in Haskell. Here's the code that I have so far, but it doesn't exactly work.

replace :: [Char] -> [Char]
replace [] = []
replace (h:t) =
    if h == "W"
    then "VV" : replace t
    else h : replace t

I want to be able to accomplish this for example: if the string is "HELLO WORLD", the result should be "HELLO VVORLD". I think words/unwords would be helpful, but not exactly sure how to implement it.

1
  • In addition to what J.Abrahamson gave in the answer here, read the types in your functions carefully. You use [Char], which means that it can only take Chars and nothing else. Note the types of (:) too. Yeah, Haskell's a lot of fun! :-) Commented Jan 29, 2014 at 9:05

3 Answers 3

5

It's worth being explicit about what String actually is. For instance, you're looking for the test case:

replace ['H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D']
==
['H', 'E', 'L', 'L', 'O', ' ', 'V', 'V', 'O', 'R', 'L', 'D']

Now, when you pattern match on a list like this the head of the list will be the first character of the string

> case "Hello world" of (c:rest) -> print c
'H'

So we can't match it with a string literal like "W". In a similar way, we can't use cons ((:)) to prepend a string to another string, we can only add a single character!

> 'P' : "hello"
"Phello"

Instead, we'll use (++) :: String -> String -> String to append two strings.

replace :: [Char] -> [Char]
replace [] = []
replace (h:t) =
    if h == 'W'
      then "VV" ++ replace t
      else h : replace t

Which ought to work as expected

> replace "Hello World"
"Hello VVorld"
Sign up to request clarification or add additional context in comments.

3 Comments

What is the runtime of ++? Isn't it beneficial to cons both characters instead, 'V' : 'V' : replace t ?
(++) is linear in the size of its left argument, so it's just about the same thing here. It's likely GHC would even inline (++) away entirely given it's applied to a constant.
Nope, it depends crucially on the idea of expanding characters only. You need some kind of sliding window to achieve word replacements.
4

With pattern matching:

replace ('W':xs) = "VV" ++ replace xs
replace (x:xs) = x : replace xs
replace [] = []

With for comprehension:

replace xs = concat [if x == 'W' then "VV" else [x] | x <- xs]

With monads:

replace = (>>= (\ x -> if x == 'W' then "VV" else [x]))

With a fold:

replace = foldr (\ x -> if x == 'W' then ("VV"++) else (x:)) []

Comments

0

The error is in "VV" :: [Char] but not Char.

And "W" is [Char], but not Char

replace :: [Char] -> [Char]
replace [] = []
replace (h:t) =
    if h == 'W'
    then 'V' : 'V' : replace t
    else h : replace t

2 Comments

Thanks, one more quick question, how can I modify this to replace words. For example, if the input string is: "I am from United States", and I want to replace "United States" with "Australia" so the result should be "I am from Australia".
@user3247171 Then you should use Landei answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.