1

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"]
3
  • 2
    Could you please include the error message in your question? (Please do not post an image, and rather copy-and-paste the message, and show us the exact code that produces the error.) Commented Oct 13, 2019 at 21:14
  • 2
    Don't remove your code just because you got an answer. Commented Oct 14, 2019 at 2:16
  • 1
    Please do not destroy content. It is not allowed by the site's rules. If you persist you will be reported to the site's moderators. Have a nice day! :) Commented Oct 15, 2019 at 23:42

1 Answer 1

3

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")]
Sign up to request clarification or add additional context in comments.

8 Comments

I'm still a little bit confused with how you write it since the main point is that we only concern about function "train" . And it's type should be like "train :: Eq a => (a -> t) -> [(a, t)] -> a -> t"
@MathCoolGuy99 Your question as posted only refers to strings. If you need train to have a specific type signature, you should edit that into your question.
@MathCoolGuy99 Further, if extend does its replacement bidirectionally, as it does in your question, then its type can't use both a and t if you want train to hardcode its use.
If train takes a string replacement function and a list of 2 - string tuples, then how can I make it similar to extend but operates on list of tuples instead?
It works now! Thank you so much!! I will mark this answer as checked!
|

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.