Однострочник
f :: String -> String -> String -> String
f str a b = let n = length a in if take n str == a then b ++ f (drop n str) a b else if str == "" then "" else head str : f (tail str) a b
Свойства решения: ленивое, работает с бесконечными строками, заменяет первое вхождение подстроки a на b в случае неоднозначной замены (напр., f "aaa" "a" "b" == "ba"), временная сложность O(N) по N = length(str).
Что можно улучшить: 1) обработка хвоста длины < length(b), 2) оформить код как многострочную читаемую функцию, 3) выделить функцию \s -> f s a b как локальную или даже поменять исходных порядок аргументов.