-- module Stack ( Stack, createStack, pop, top, push, isEmpty ) where


type Stack a = [a]

createStack :: Stack a
createStack = []

pop :: Stack a -> Stack a
pop (x:xs)  = xs

top :: Stack a -> a
top (x:xs)  = x

push :: Stack a -> a -> Stack a
push ys y  = y:ys

isEmpty :: Stack a -> Bool
isEmpty xs  = length xs == 0


-------------------------------------------------------------------------

-- import Stack ( Stack, createStack, pop, top, push, isEmpty )



-- Definition des Datentyps File
type File a = (Stack a, Stack a)


createFile :: File a
createFile = (createStack, createStack)

write :: File a -> a -> File a
write (k1, k2) x = (push k1 x, k2)

-- ohne das 'F' meckert Hugs: die Funktion 'read' gibt's schon...
readF :: File a -> a -> File a
readF (k1, k2) x = (k1, push k2 x)

reset :: File a -> File a
reset (k1, k2) | isEmpty k1 = (createStack, k2)
               | otherwise  = reset (pop k1, push k2 (top k1))

skip :: File a -> File a
skip (k1, k2) | isEmpty k1 && isEmpty k2 = error "skip on empty file"
              | isEmpty k2               = error "skip at eof"
              | otherwise                = (push k1 (top k2), pop k2)

eof :: File a -> Bool
eof (k1, k2) = isEmpty k2

-- show gibt's auch schon, darum nennen wir's halt get
get :: File a -> a
get (k1, k2) | isEmpty k1 && isEmpty k2 = error "get on empty file"
             | isEmpty k2               = error "get at eof"
             | otherwise                = top k2

put :: File a -> a -> File a
put (k1, k2) x = (push k1 x, createStack)


-- Beispiel-Aufruf (Vergleiche G. Goos, Vorlesungen über Informatik - Band 1, Seite 300):
-- (get . skip . reset) (write (write (write (write createFile 1) 2) 3) 4) 
-- liefert 2