Home > other >  Is there an easier way to write this function and only using prelude from Haskell?
Is there an easier way to write this function and only using prelude from Haskell?

Time:09-23

So I'm pretty new to Haskell, and are trying to solve an assignment, I've solved it, but I'm wondering if there is an easier or prettier way to make a function do the same as my wordChange. I'm trying to only use what is already in prelude.

dictionaryChecker _ [] = False
dictionaryChecker word (x:xs) = if elem word (snd x) then True else dictionaryChecker word xs

wordChange :: String -> String 
wordChange str = unwords (map (\s -> if length (translate s) > 0 then (translate s) 
else if (dictionaryChecker s dictionary) then concat (replicate (length s) "*")
else s) (words str))

translate :: String -> String 
translate str = contains str dictionary

contains _ [] = ""
contains str (x:xs) = if elem str (snd x) then fst x else contains str xs

CodePudding user response:

I'd suggest to use the lookup function from Prelude, which takes a key and a list of tuples (a.k.a a dictionary) and returns Maybe value. This simplfies your function a lot. Also, if changeWord uses a dictionary, it should be explicit instead of using a global variable. Below, a partial solution: since it is an assignment I think you should try to complete it ;)

changeWord :: [(String, String)] -> String -> String
changeWord dic s = unwords $ substitute ws
  where -- ws is just the list of words s has  
        ws = words s
        -- the function substitute does the word changing recursively. Try to complete it
        substitute []     = []
        substitute (x:xs) = 
         case lookup x dic of -- look for x in the dictionary and returns the value if found
           Nothing -> undefined --complete
           Just y  -> undefined --complete

CodePudding user response:

An obfuscated answer: earn a gold star from your professor if you can explain how it works, and be accused of copying from the internet if you can't:

wordChange :: [(String, String)] -> String -> String
wordChange dict = unwords . map (foldr const <*> (`lookup` dict)) . words

CodePudding user response:

Your dictionaryChecker is in essence an any :: Foldable f => (a -> Bool) -> f a -> Bool with elem word . snd as condition:

dictionaryChecker :: (Foldable f, Foldable g, Eq a) => a -> f (b, g a) -> Bool
dictionaryChecker word = any (elem word . snd)

as for a translate, we can work with a section of an infix operator [Haskell-wiki] to make a point-free function:

translate :: String -> String 
translate = (`contains` dictionary)

and for contains we can work with a foldr :: Foldable f => (a -> b -> b) -> b -> f a -> b

contains :: (Foldable f, Foldable g, Eq a) => a -> f (String, g a) -> String
contains str = foldr (\x y -> ifthenelse …) ""

I leave implementing the parts as an exercise.

  • Related