-1

the problem is to check whether parentheses in a string is properly closed or not. For Haskell implementation, so far I have following. It looks quite awkward. I am looking for a more "Haskell-style" or more elegant implementation.

import Data.List

isValidParentheses :: String -> Bool
isValidParentheses = isValidHelper . (filter isParenthese)

getIndex :: (Eq a) => a -> [a] -> Int
getIndex c xs =  getOut (elemIndex c xs)
  where getOut (Just x) = x
        getOut Nothing = -1

isLeftParenthese :: Char -> Bool
isLeftParenthese c = (getIndex c "{[(") /= -1

isRightParenthese :: Char -> Bool
isRightParenthese c = (getIndex c "}])") /= -1

isParenthese :: Char -> Bool
isParenthese c = isLeftParenthese c || isRightParenthese c


isValidHelper :: String -> Bool
isValidHelper xs = helper xs []
  where helper (x:xs) []     | isRightParenthese x = False
                             | otherwise = helper xs [x]
        helper [] st = null st
        helper (x:xs) (s:ss) | isLeftParenthese x = helper xs (x:s:ss)
                              | ((getIndex x "}])") /= (getIndex s "{[(")) = False
                              | otherwise = helper xs ss

Thanks

Yan Zhu
  • 4,036
  • 3
  • 21
  • 37
  • `getIndex c xs /= -1` can be replaced by `elem c xs`. After this, `getIndex` should be removed: you can compare the `Maybe Int` result of `elemIndex` directly, if you want. Transforming `Nothing` into `-1` is very un-Haskellish: at best it is useless (as in this case), at worst it prods the programmer to forget about the "not found" case. Finally, your code does not handle other chars e.g. `a(b[c]d)e` is not valid -- this is intended, right? – chi Jan 04 '15 at 23:20
  • possible duplicate of [Checking if a string consists of balanced parenthesis](http://stackoverflow.com/questions/7209260/checking-if-a-string-consists-of-balanced-parenthesis) – max taldykin Jan 05 '15 at 11:43

1 Answers1

6
  • Loop through the string
  • Store opening parentheses in stack
  • Pop matching parentheses out of the stack
  • Check if stack is empty at the end

    isValid = loop []
      where
        match '(' ')' = True
        match '{' '}' = True
        match '[' ']' = True
        match  _   _  = False
    
        loop st [] = null st
        loop st (x:xs)
          | x `elem` "([{" = loop (x:st) xs
          | x `elem` ")]}" = case st of
            open : st' | match open x -> loop st' xs
            _ -> False -- unmatched close
          | otherwise = loop st xs
    
max taldykin
  • 12,459
  • 5
  • 45
  • 64