module Stack (Stack, push, pop, isEmpty, runStack)
where
import Control.Monad

newtype Stack a b = Stack ([a] -> ([a], b))

instance Monad (Stack a) where
    return result = Stack (\state -> (state, result))
    Stack priorFunction >>= nextAction =
	let combinedFunction priorState = 
                let (currentState, priorResult) = priorFunction priorState
		    Stack nextFunction = nextAction priorResult
                 in nextFunction currentState
         in Stack combinedFunction

push :: a -> Stack a ()

push item = Stack $ \priorState -> (item : priorState, ())

pop :: Stack a a

pop =
    Stack currentFunction
    where
    currentFunction [] = error "stack empty"
    currentFunction (item : remainder) = (remainder, item)

isEmpty :: Stack a Bool

isEmpty = Stack $ \state -> (state, null state)

runStack :: Stack a b -> b

runStack (Stack function) = snd (function [])
