Reputation: 13
I want to write a function called trained
that takes a string replacement function and a list of word pairs (two-tuples of strings).
I have tried using map
and lambda function but still getting some error. Any help on this problem would be much appreciated!
Function train
should have this type of signature: train :: Eq a => (a -> t) -> [(a, t)] -> a -> t
Here is some error:
Couldn't match expected type
[Char] -> b'
with the actual type[[Char] -> [Char]]
Here is my code:
extend repl old new = \str -> if (str == old) then new
else if (str == new) then old
else (repl str)
train fn lst = map (\(a,b) -> extend fn a b) lst
The function train should work out like this:
In: let improved = train (\s->s) [("kittens","puppies"),
("tea","coffee"),("Java","Haskell")]
In: map improved ["my","favorite","things","are",
"kittens","Java","tea","and","rainbows"]
Out: ["my","favorite","things","are","puppies","Haskell","coffee","and","rainbows"]
Upvotes: 1
Views: 213
Reputation: 48572
You're trying to call map improved
, but the first argument to map
has to be a function, and :t improved
shows you that improved
is actually a list of functions: improved :: [[Char] -> [Char]]
. The problem is that train
is returning a list of functions, rather than a single composed function. To fix that, change map (\(a,b) -> extend fn a b)
to foldr (\(a,b) f -> extend f a b) fn
.
Also, your code is a bit unidiomatic and complex. Here's how I'd write it:
extend :: Eq a => (a, a) -> (a -> a) -> a -> a
extend (old, new) repl str
| str == old = new
| str == new = old
| otherwise = repl str
train :: Eq a => (a -> a) -> [(a, a)] -> a -> a
train = foldr extend
improved :: String -> String
improved = train id [("kittens","puppies"),("tea","coffee"),("Java","Haskell")]
Now that you edited your question to include a required type signature, there's a change you have to make: extend
must only do its replacement unidirectionally (i.e., it can't test for str == new
and replace it with old
). Here's how it would look idiomatically after that:
extend :: Eq a => (a, t) -> (a -> t) -> a -> t
extend (old, new) repl str
| str == old = new
| otherwise = repl str
train :: Eq a => (a -> t) -> [(a, t)] -> a -> t
train = foldr extend
improved :: String -> String
improved = train id [("kittens","puppies"),("tea","coffee"),("Java","Haskell")]
Upvotes: 3