-- |
-- Module      : Pila
-- Description : TAD de las pilas.
-- License     : Creative Commons
-- Maintainer  : José A. Alonso
-- 
-- TAD (tipo abstracto de datos) de las pilas.
--
-- Este módulo contiene el código del TAD de las pilas
-- estudiado en el <http://bit.ly/1F5SqpU tema 14> del curso.

module I1M.Pila
  (Pila,
   vacia,    -- Pila a
   apila,    -- a -> Pila a -> Pila a
   cima,     -- Pila a -> a
   desapila, -- Pila a -> Pila a
   esVacia   -- Pila a -> Bool
  ) where

-- | Tipo de dato de las pilas.
data Pila a = Vacia
            | P a (Pila a)
  deriving Pila a -> Pila a -> Bool
(Pila a -> Pila a -> Bool)
-> (Pila a -> Pila a -> Bool) -> Eq (Pila a)
forall a. Eq a => Pila a -> Pila a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Pila a -> Pila a -> Bool
$c/= :: forall a. Eq a => Pila a -> Pila a -> Bool
== :: Pila a -> Pila a -> Bool
$c== :: forall a. Eq a => Pila a -> Pila a -> Bool
Eq

-- Procedimiento de escritura de pilas.
instance (Show a) => Show (Pila a) where
  showsPrec :: Int -> Pila a -> ShowS
showsPrec Int
_ Pila a
Vacia String
cad   = Char -> ShowS
showChar Char
'-' String
cad
  showsPrec Int
_ (P a
x Pila a
s) String
cad = a -> ShowS
forall a. Show a => a -> ShowS
shows a
x (Char -> ShowS
showChar Char
'|' (Pila a -> ShowS
forall a. Show a => a -> ShowS
shows Pila a
s String
cad))

-- | p1 es un ejemplo de pila que se usará en los siguientes ejemplos:
-- 
-- > ghci> p1
-- > 1|2|3|-
-- p1 :: Pila Int
-- p1 = apila 1 (apila 2 (apila 3 vacia))

-- | vacia es la pila vacía. Por ejemplo,
--
-- >   ghci> vacia
-- >   -
vacia :: Pila a
vacia :: Pila a
vacia = Pila a
forall a. Pila a
Vacia

-- | (apila x p) es la pila obtenida añadiendo x encima de la pila p. Por
-- ejemplo,
--
-- > apila 4 (apila 1 (apila 2 (apila 3 vacia)))  ==  4|1|2|3|-
apila :: a -> Pila a -> Pila a
apila :: a -> Pila a -> Pila a
apila = a -> Pila a -> Pila a
forall a. a -> Pila a -> Pila a
P 

-- | (cima p) es la cima de la pila p. Por ejemplo,
--
-- > cima (apila 1 (apila 2 (apila 3 vacia)))  ==  1
cima :: Pila a -> a
cima :: Pila a -> a
cima Pila a
Vacia   = String -> a
forall a. HasCallStack => String -> a
error String
"la pila vacia no tiene cima"
cima (P a
x Pila a
_) =  a
x

-- | (desapila p) es la pila obtenida suprimiendo la cima de la pila
-- p. Por ejemplo,
--
-- > desapila (apila 1 (apila 2 (apila 3 vacia)))  ==  2|3|-
desapila :: Pila a -> Pila a
desapila :: Pila a -> Pila a
desapila Pila a
Vacia   = String -> Pila a
forall a. HasCallStack => String -> a
error String
"no se puede desapila la pila vacia"
desapila (P a
_ Pila a
p) = Pila a
p

-- | (esVacia p) se verifica si p es la pila vacía. Por ejemplo,
--
-- > esVacia (apila 1 (apila 2 (apila 3 vacia)))  ==  False
-- > esVacia vacia                                ==  True
esVacia :: Pila a -> Bool
esVacia :: Pila a -> Bool
esVacia Pila a
Vacia = Bool
True
esVacia Pila a
_     = Bool
False