Understanding the assignment
Your assignment says that you should use words
and unwords
:
words :: String -> [String]
unwords :: [String] -> String
It is therefore clear, that you need something to operate on a list of Strings:
innerFunc :: [String] -> [String]
This will enable you to use unwords . innerFunc . words
. However, that looks just like mapping over Strings with a correct replacement function:
innerFunc = map f
where f
should be something like
f :: String -> String
So it's enough if you manage to create a function that replaces a single word correctly.
Solving the assignment
As stated above, we're now looking for a function that replaces a single word correctly. For convenience, lets create a type synonym Word
*, so we know whether this is currently meant for a single word or a whole sentence.
* note that Haskell provides Word
already in Data.Word
, but that is something completely different, namely a unsigned Int
variant, so it's just for convenience in the following code
type Word = String
Replace a single word by a single replacement patterns
Lets start very simple. We shall write a function that works only for a single word:
replaceSimple :: (Word, Word) -> Word -> Word
replaceSimple (orig, repl) word = if orig == word then repl else word
It's clear that this will replace word
iff orig == word
:
replaceSimple ("fox", "cat") "fox" == "cat"
replaceSimple ("fox", "cat") "dog" == "dog"
Replace a single word by a many replacement patterns
Now we want to use that knowledge for a function that still operates on a single Word, but takes it replacements from a list and applies the first one that matches:
replaceSingle :: [(Word, Word)] -> Word -> Word
replaceSingle [] word = word
replaceSingle (r:rs) word = if word == fst r then snd r else replaceMany rs word
Look closely: replaceSingle
will leave the word unchanged iff the list of replacements is empty or there's a identitiy replacement like ("fox","fox")
before any other replacement. Otherwise it's going to exchange word
with the replacement if they match or try the rest of the replacement rules.
Putting things together
Now replaceSingle
almost looks like f
above, doesn't it? And it sure is! All you need to provide is the list of replacements:
:t replaceSingle [("fox","cat"),("he","she")]
replaceSingle [("fox","cat"),("he","she")] :: String -> String
All you need to do is to map
this function as written above.
Putting together the functions map
, replaceSingle
, unwords
and words
is left as an exercise to the reader.