data Pila e = Vacia
| Apilar e (Pila e)
deriving Show
es_vacia :: Pila e -> Bool
primero :: Pila e -> e -- se aplica a pilas no vacías
desapilar :: Pila e -> Pila e -- se aplica a pilas no vacías
es_vacia Vacia = True
es_vacia (Apilar e p) = False
primero (Apilar e p) = e
desapilar (Apilar e p) = p
-- Ejemplos
p0 = Vacia :: Pila Char
p1 = Apilar ']' p0
p2 = Apilar ')' p1
p3 = Apilar '}' p2
p4 = Apilar '>' p3
balanceo :: String -> Bool
balanceo as = balanceo_rec as Vacia
balanceo_rec :: String -> Pila Char -> Bool
balanceo_rec [] p = es_vacia p
balanceo_rec (a:as) p =
if a `elem` ['(', '[', '{', '<']
then balanceo_rec as (Apilar (derecho a) p)
else if (a `elem` [')', ']', '}', '>'])
then (not (es_vacia p)) && (a == primero p) && (balanceo_rec as (desapilar p))
else balanceo_rec as p
derecho :: Char -> Char
derecho '(' = ')'
derecho '[' = ']'
derecho '{' = '}'
derecho '<' = '>'