Search code examples
haskellparse-errorguard-clause

How to solve Haskell parse error on input 'otherwise'


I have a function which returns a list of halves of palindromes found from the input list. It works if I use an if-statement on one row but I'd like to use guards. Guards give me a parse error. I read many cases giving this kind of error, but I didn't figure out my case. Here is the code:

palindromeHalfs :: [String] -> [String]
palindromeHalfs xs = map firstHalf (filter palindrome xs)
    where
    firstHalf :: String -> String
    firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
                 | otherwise                = take ((div (length ys 2) + 1) ys
    palindrome :: String -> Bool
    palindrome str | str == reverse str = True
                   | otherwise          = False 

And the error:

palindromeHalfs.hs:6:20: error: parse error on input `otherwise'
  |
6 |                  | otherwise                = take ((div (length ys 2) + 1) ys
  |                    ^^^^^^^^^

The function works if I replace

firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
             | otherwise                = take ((div (length ys 2) + 1) ys

with

firstHalf ys = if (length (ys !! 0)) `rem` 2 == 0 then take ((div (length (ys !! 0)) 2)) ys 
                                                  else take ((div (length (ys !! 0)) 2) + 1) ys

In my code the if-statement is one row, it didn't fit here. I'd appreciate if someone can tell me which is preferred, if or guards. And of course, why my guards do not work.


Solution

  • The parentheses are not balanced in

    take ((div (length ys 2)) ys
    

    As for style, guards are much preferred over if/else in cases where either may be used. Note also that even :: Integral a => a -> Bool is a function that exists; you don't have to invent it with rem.