3

I would like to replace a substring with a string in Haskell, without using external libraries, and, if it is possible, with good performance.

I thought about using the Data.Text replace functions, but I don't want to port my entire program to use the Text type instead of Strings. Would packing the String into a Text value, then replacing what I wanted to, then unpacking that Text value to a String be slow on a lot of Strings?

4
  • 12
    For many interpretations of "good performance" you will need to replace String with Text. Commented Feb 14, 2013 at 17:40
  • 4
    Porting your entire program to use Text instead of String is unlikely to be difficult, just tedious. There are corner cases concerning APIs using Strings without the option to use Text/ByteString, but for the most part it's just a matter of changing the type in one place and then correcting the type errors that crop up elsewhere. Commented Feb 14, 2013 at 17:52
  • if you want to replace a Data.Text, use replace Commented Aug 13, 2020 at 15:22
  • Why doesn't ByteString have a replace function like the one in Text? Commented Jun 8, 2022 at 17:53

2 Answers 2

8

Try this (untested):

replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace needle replacement haystack
  = case begins haystack needle of
      Just remains -> replacement ++ remains
      Nothing      -> case haystack of
                        []     -> []
                        x : xs -> x : replace needle replacement xs

begins :: Eq a => [a] -> [a] -> Maybe [a]
begins haystack []                = Just haystack
begins (x : xs) (y : ys) | x == y = begins xs ys
begins _        _                 = Nothing

But in general you will get performance gains from switching your program to use Texts instead of Strings.

Sign up to request clarification or add additional context in comments.

4 Comments

ok, im gonna port my program to the text type, but how would i read a file as text instead of a string? there is no function for that, like when using bytestrings. do i just convert the string to a text type?
@nils8950 There are no functions for that? Are you sure?
@ThomasM.DuBuisson thanks!! i didnt find that for some reason.
@nils8950 Probably because you didn't use hoogle or grep! Eyeballs have been inferior tools since at least the 80s ;-)
6

Here is my solution

import Data.List (intercalate)
import Data.List.Split (splitOn)

replace from to = intercalate to . splitOn from

Example

replace "squirrel" "platypus" "Daddy, I want a squirrel !"

Daddy, I want a platypus !

Comments

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.