-2

I have enter code here an assignment in Haskell and in one of the tasks I have to translate an input word according to a dictionary that is already in the file. This is an example of the a line from the dictionary:

dictionary = [ 
        ("doubleplusgood",["excellent", "fabulous", "fantastic", "best"]),
]

If the input is "excellent" the task says that my translator function should return output "doubleplusgood":

translate "excellent" = "doubleplusgood"

I have been trying to solve this task for hours now and I think my thought are just going in a circle, so I was wondering if anyone has any advice on where I should begin in order to solve the task? I am, by the way, not allowed to import any other packages other than Prelude.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
amonmi
  • 17
  • 3
  • 3
    This q looks eerily similar to https://stackoverflow.com/questions/69222788/how-to-use-a-skeleton-program-in-haskell. You aren't both doing the same homework by any chance? What have you tried so far? At least you can tell us the types of `dictionary` and `translate`. – AntC Sep 17 '21 at 12:48
  • @AntC, yes, I think we're doing the same task. the type of dictionary is dictionary :: [([Char], [[Char]])] and the type of translate is translate :: String -> String. What I've tried so far is using "case lookup x dictionary of", but I'm not sure what I've written makes sense – amonmi Sep 17 '21 at 13:26
  • @AntC now after reading that link, they're similar, but this one is much clearer. in fact the other one is just _not clear_ at all. – Will Ness Sep 17 '21 at 13:59

1 Answers1

1

Well you can start with what you already know to be true, defining

translate "excellent" = "doubleplusgood"

(suspend your disbelief for a moment, will you).

Yes this is a valid definition. But it doesn't refer to dictionary, so we can address that by defining

translate "excellent" = matchup "excellent" dictionary 

matchup "excellent" dict = "doubleplusgood"

Except that it is too specific of course. So we generalize a little bit as

translate excellent = matchup excellent dictionary 

matchup excellent dict = "doubleplusgood"

Now the matchup is just cheating. We can try make it do some actual work as

matchup "excellent" 
  [("doubleplusgood",[ "excellent", "fabulous", "fantastic", "best"])]
  =
    "doubleplusgood"

All these variations so far are just writing down what you already had.

But we had it generalized before, so

matchup excellent
  [("doubleplusgood",[ excellent, "fabulous", "fantastic", "best"])]
  =
    "doubleplusgood"

and that's an error now. We can't have two occurrences of the same variable in our arguments. It's forbidden in Haskell. So it must be

matchup excellent1
  [("doubleplusgood",[ excellent2, "fabulous", "fantastic", "best"])]
  =
    "doubleplusgood"

We are definitely going somewhere with this. But wait, we didn't use the two variables at all. They are supposed to have the same value, aren't they. So let's write that down:

matchup excellent1
  [("doubleplusgood",[ excellent2, "fabulous", "fantastic", "best"])]
    | excellent1 == excellent2
  =
    "doubleplusgood"

Well but what's with all these other entries in the synonyms list? And their "translation"?

matchup excellent1
  [(doubleplusgood,[ excellent2, fabulous, fantastic, best])]
    | excellent1 == excellent2
  =
    doubleplusgood

Now this is a bona fide Haskell definition. Almost. Why should the list of synonyms have this fixed length? Why would there be just one entry in the dictionary?

We proceed by wishful thinking (Thank You) and write

matchup excellent1 (
   (doubleplusgood, synonyms)
   :
   more )
    | present excellent1 synonyms
  =
    doubleplusgood

And now we must also define this present. But first, what should we do with more? Under what condition?

matchup excellent1 (
   (doubleplusgood, synonyms)
   :
   more )
    | present excellent1 synonyms
  =
    doubleplusgood
    | otherwise
  =
    somethingelse excellent1 more 

But what should somethingelse do? Isn't it exactly what matchup is doing?

etc. etc. etc.

I think You can continue from here.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Hi, thanks for the help, but I'm not sure I can use this method in my task as the dictionary I have been provided is extremely long and writing this type of code for each instance in the dictionary would not be practical. I think I should try to compare every element that is in the second part (elemnt) of the head of the dictionary with what I'm writing in the input, but I'm not sure how to do this. – amonmi Sep 18 '21 at 10:15
  • 1
    of course this is not what I suggest here at all. I present to you a way to develop your code by gradual generalization. in particular, the last bits with "`more`" specifically deal with the case where the list is long. also, when I switched a string `"excellent"` to a variable `excellent` you're supposed to realize that the name of the variable does not matter and it can hold any value. that's why I switched to the explicit `==` testing. – Will Ness Sep 18 '21 at 14:54
  • as to the comparison you mention, this is left as the task for the function `present`, or better name would be `isPresent`. in fact, a built-in function like that already exists. try to find out its type from the context of its use, then use [hoogle](https://hoogle.haskell.org/?hoogle=Eq+a+%3D%3E+a+-%3E+%5Ba%5D+-%3E+Bool&scope=set%3Astackage) to find this function. if it's not in the Prelude, you can write it, according to the same principles as this `matchup` function: you define `isPresent a (x:xs) = ....something....` and `isPresent a [] = ....something....` and that's all. – Will Ness Sep 18 '21 at 14:56