I wrote the following program to check strings for balanced parenthesis:
isBalanced xs = isBalanced\' xs []
isBalanced\' [] [] = True
isBalanced\' [] _ = False
import Data.List (foldl')
isBalanced xs = null $ foldl' op [] xs
where
op ('(':xs) ')' = xs
op ('[':xs) ']' = xs
op ('{':xs) '}' = xs
op xs x = x:xs
The fold builds up a stack of previously encountered characters, stripping away any matches as it finds them. If you end up with an empty list, the string is balanced.
The disadvantage of using a left fold is that the entire string must always be scanned through. It would be nice to abort the operation with a failure should a closing brace be found without a matching opening brace. Here's a version that does just that.
import Control.Monad (foldM)
isBalanced' xs = maybe False null $ foldM op [] xs
where
op ('(':xs) ')' = Just xs
op ('[':xs) ']' = Just xs
op ('{':xs) '}' = Just xs
op xs x | x `elem` ")]}" = Nothing
| otherwise = Just (x:xs)