Search code examples
haskellrecursionlist-comprehension

How to detect two adjacent identical characters in Haskell using list comprehension and recursion?


I am trying to write a function detadj :: String -> Bool that takes a string and returns true if the string contains two adjacent characters that are identical. For example:

detadj "" == False
detadj "s" == False
detadj "ss" == True
detadj "Misisipi" == False
detadj "Mississippi" == True
detadj "single-dash" == False
detadj "double--dash" == True

I have two versions of the function one in list comprehension, which is faulty in many cases, but the most prevalent one is when detadjlc ["ss"] which will output an empty list due to the usage of the (x:y:xs) bit:

detadjlc :: String -> Bool
detadjlc [] = False
detadjlc [x] = False
detadjlc (x:y:xs) = head[ x == y && isAlpha x == isAlpha y | (x,y) <- zip (x:y:xs) xs ]

And recursion (this does not work when the input is something like detadjr [" ee"] which produces False instead of True):

detadjr :: String -> Bool
detadjr [] = False
detadjr [x] = False
detadjr (x:y:xs) | x == y = True
           | otherwise = d xs

What are some ways to fix these?


Solution

  • Your recursive function is fine, except for one small detail: you forgot to put y back on the list for the recursive call. (I assume d is a typo for detadjr.) Just because x and y are different doesn't mean y and the first character of xs might not be the same.

    detadjr :: String -> Bool
    detadjr (x:y:xs) = (x == y) || detadjr (y:xs)
    detadjr _ = False
    

    (If you check strings of 2 or more characters first, then singleton and empty lists can be collapsed into a single base case.)