
so after being inspired by the continual excellent help here, i am trying my hand at writing a multiple replace using Useful.replace Useful.replace origStr pattStr replStr gives for Useful.replace "This original string" "orig" "very orig" "This very original string" what i want to do is something like multRepl origStr [patt1,patt2] [repl1,repl2] so we get from multRepl "This original string" ["orig","ing"] ["very orig","ucture"] "This very original structure" what i have come up with is: multRepl :: String -> [String] -> [String] -> [String] multRepl str ss rs = [U.replace str a b | (a,b) <- (zip ss rs)] this produces in 2 passes: ["This very original string","This very original structure"] to get the final result, i could just last multRepl but i would like to know if this is a good way to do things. i suppose going through the incremental steps is obligatory, but after printing out the result and seeing these steps, it feels like i'm producing throw away stuff - though perhaps that's just an illusion stemming from a similar function php5 has where you get the result without seeing anything behind the scenes. -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

On Thu, 1 Jul 2010 21:57:20 -0700
prad
but i would like to know if this is a good way to do things.
ooops i just figured out that this doesn't work as stated. i was looking at replacement in a large file and got mixed up. the above code only replaces things one by one, so doing a last only produces the last change. what i need is something to merge the changes together ... so back to the drawing board! -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

On Thu, 1 Jul 2010 22:31:28 -0700
prad
so back to the drawing board!
here's what emerged: ====== #!/usr/bin/env runghc module Main where import Useful as U main = do let str = "This is original string" let ss = ["orig","ing"] let rs = ["very orig","ucture"] putStrLn $ head (multRepl str ss rs) --multRepl :: String -> [String] -> [String] -> [String] multRepl [] _ _ = [] multRepl str (s:ss) (r:rs) = do let newStr = U.replace str s r if (length ss) == 0 then return newStr else multRepl newStr ss rs ======= this does produce the correct output: This is very original structure and here are my questions: 1. the type *Main Useful> :t multRepl multRepl :: (Eq t) => [t] -> [[t]] -> [[t]] -> [[t]] but i have it returning newStr which equals U.replace str s r and the type of U.replace is String as shown below *Main Useful> :t Useful.replace Useful.replace :: (Eq a) => [a] -> [a] -> [a] -> [a] so why is it returning [String] when newStr isn't a list of strings? 2. is the way i've done it proper haskellian? it took me quite some time to think this out trying to find my way through the fog of imperative programming. (my apologies for replying to my own posts - as well as my appreciation for your assistance) -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

I think your first attempt using list comprehension is nearly ok but is in fact a fold: multRepl str ss rs = foldl (uncurry . replace) str (zip ss rs) or something similar. On Thu, 2010-07-01 at 23:58 -0700, prad wrote:
On Thu, 1 Jul 2010 22:31:28 -0700 prad
wrote: so back to the drawing board!
here's what emerged:
====== #!/usr/bin/env runghc
module Main where
import Useful as U
main = do
let str = "This is original string" let ss = ["orig","ing"] let rs = ["very orig","ucture"]
putStrLn $ head (multRepl str ss rs)
--multRepl :: String -> [String] -> [String] -> [String] multRepl [] _ _ = [] multRepl str (s:ss) (r:rs) = do let newStr = U.replace str s r if (length ss) == 0 then return newStr else multRepl newStr ss rs =======
this does produce the correct output: This is very original structure
and here are my questions:
1. the type *Main Useful> :t multRepl multRepl :: (Eq t) => [t] -> [[t]] -> [[t]] -> [[t]]
but i have it returning newStr which equals U.replace str s r and the type of U.replace is String as shown below *Main Useful> :t Useful.replace Useful.replace :: (Eq a) => [a] -> [a] -> [a] -> [a]
so why is it returning [String] when newStr isn't a list of strings?
2. is the way i've done it proper haskellian? it took me quite some time to think this out trying to find my way through the fog of imperative programming.
(my apologies for replying to my own posts - as well as my appreciation for your assistance)

On Friday 02 July 2010 08:58:56, prad wrote:
On Thu, 1 Jul 2010 22:31:28 -0700
prad
wrote: so back to the drawing board!
here's what emerged:
====== #!/usr/bin/env runghc
module Main where
import Useful as U
main = do
let str = "This is original string" let ss = ["orig","ing"] let rs = ["very orig","ucture"]
putStrLn $ head (multRepl str ss rs)
--multRepl :: String -> [String] -> [String] -> [String] multRepl [] _ _ = [] multRepl str (s:ss) (r:rs) = do let newStr = U.replace str s r if (length ss) == 0
don't do that. If you want to know whether a list is empty, use null. if null ss then ... calculating the length of a list can be very costly.
then return newStr else multRepl newStr ss rs =======
What you probably want is multRepl [] _ _ = [] multRepl str (s:ss) (r:rs) = let newStr = U.replace str s r in multRepl newStr ss rs multRepl str _ _ = str
this does produce the correct output: This is very original structure
and here are my questions:
1. the type *Main Useful> :t multRepl multRepl :: (Eq t) => [t] -> [[t]] -> [[t]] -> [[t]]
but i have it returning newStr which equals U.replace str s r and the type of U.replace is String as shown below *Main Useful> :t Useful.replace Useful.replace :: (Eq a) => [a] -> [a] -> [a] -> [a]
so why is it returning [String] when newStr isn't a list of strings?
Because return in Haskell is entirely different from the return you may know from C/Java/... In Haskell, return is an ordinary function with the type return :: Monad m => a -> m a The first equation of multRepl, multRepl [] _ _ = [] says multRepl's result is some list type ([a], with an as yet unkown a) later, you have if something then return newStr else ... newStr is a list of something (by the type of Useful.replace, newStr has the same type as multRepl's first argument), so, by the type of return, multRepl's result must be have the type m ([b]) for some Monad m and some type b (the type of elements of str). Together with what we know from the first equation, it follows m = [] (indeed, [] is a Monad), so the result type is [[b]]
2. is the way i've done it proper haskellian? it took me quite some time to think this out trying to find my way through the fog of imperative programming.
Bad argument order. If you had replace pattern replacement string you could make multRepl pats reps = foldr (.) id (zipWith replace pats reps) Using a higher order combinator like foldr is more haskellish than explicit recursion :)
(my apologies for replying to my own posts - as well as my appreciation for your assistance)

On Friday 02 July 2010 09:36:47, Daniel Fischer wrote:
multRepl pats reps = foldr (.) id (zipWith replace pats reps)
Oops, wrong order of replacings. We could use one of foldr (flip (.)) id (zipWith replace pats reps) foldr (.) id (reverse (zipWith replace pats reps) multRepl pats reps string = foldl (flip id) string (zipWith replace pats reps) or many more.

Hi,
--multRepl :: String -> [String] -> [String] -> [String]
Personally I woud use a list of pairs to represent the target/replacements: multRepl :: String -> [(String,String)] -> String That way you are guaranteed that for each target there is a replacement and don't need to handle the cases where both lists have different lengths. multRepl str srs = foldl (\acc (s,r) -> replace acc s r) str srs or in point-free form: multRepl = foldl (\acc (s,r) -> replace acc s r) or more succinctly (as mentionned before): multRepl = foldl (uncurry . replace) Patrick
multRepl [] _ _ = [] multRepl str (s:ss) (r:rs) = do let newStr = U.replace str s r if (length ss) == 0 then return newStr else multRepl newStr ss rs =======
this does produce the correct output: This is very original structure
and here are my questions:
1. the type *Main Useful> :t multRepl multRepl :: (Eq t) => [t] -> [[t]] -> [[t]] -> [[t]]
but i have it returning newStr which equals U.replace str s r and the type of U.replace is String as shown below *Main Useful> :t Useful.replace Useful.replace :: (Eq a) => [a] -> [a] -> [a] -> [a]
so why is it returning [String] when newStr isn't a list of strings?
2. is the way i've done it proper haskellian? it took me quite some time to think this out trying to find my way through the fog of imperative programming.
(my apologies for replying to my own posts - as well as my appreciation for your assistance)
-- In friendship, prad
... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- ===================== Patrick LeBoutillier Rosemère, Québec, Canada

multRepl = foldl (uncurry . replace)
Actually I've been thinking about this and I can't quite figure out how it works: I understand the type of replace is replace :: (Eq a) => [a] -> [a] -> [a] -> [a] but I can't figure out how the type of (uncurry . replace) becomes uncurry . replace :: (Eq a) => [a] -> ([a], [a]) -> [a] ? Patrick -- ===================== Patrick LeBoutillier Rosemère, Québec, Canada

On Friday 02 July 2010 23:15:22, Patrick LeBoutillier wrote:
multRepl = foldl (uncurry . replace)
Actually I've been thinking about this and I can't quite figure out how it works:
I understand the type of replace is
replace :: (Eq a) => [a] -> [a] -> [a] -> [a]
but I can't figure out how the type of (uncurry . replace) becomes
uncurry . replace :: (Eq a) => [a] -> ([a], [a]) -> [a]
?
let's make it foo :: a -> b -> c -> d to not get confused by the fact that replace's arguments and result all have the same type. So, what does uncurry . foo do? Well, (f . g) x = f (g x), so when we apply (uncurry . foo) to an argument x, we get uncurry (foo x) Now, x is the first argument of foo, so x :: a, and (foo x) :: b -> c -> d That means (foo x) has just the type uncurry expects, hence uncurry (foo x) :: (b, c) -> d Now write uncurry (foo x) again as (uncurry . foo) x :: (b, c) -> d and remove x again, so (uncurry . foo) :: a -> (b, c) -> d finally, remember that foo is actually replace and hence all four type variables stand for the same list type (with an Eq constraint).
Patrick
participants (4)
-
Daniel Fischer
-
jean verdier
-
Patrick LeBoutillier
-
prad