# Living in the open world(2)

```{-# LANGUAGE TypeSynonymInstances #-}

module A where

type StackA = []

top :: StackA a -> a

pop :: StackA a -> StackA a
pop = tail

push :: a -> StackA a -> StackA a
push = (:)

move :: StackA a -> c a -> (a -> c a -> c a) -> (StackA a, c a)
move s1 s2 fpush = (s1',s2')
where
x = top s1
s1' = pop s1
s2' = fpush x s2
```

```module B where
data StackB a = Nil | Cons a (StackB a) deriving Show

top :: StackB a -> a
top (Cons x _) = x

pop :: StackB a -> StackB a
pop (Cons x s) = s

push :: a -> StackB a -> StackB a
push x s = Cons x s

move :: StackB a -> c a -> (a -> c a -> c a) -> (StackB a, c a)
move s1 s2 fpush = (s1',s2')
where
x = top s1
s1' = pop s1
s2' = fpush x s2
```

```module C where

import A (StackA(..))
import qualified A hiding (StackA)
import B (StackB(..))
import qualified B hiding (StackB)

class Stack s where
top :: s a -> a
pop :: s a -> s a
push :: a -> s a -> s a
move :: s a -> c a -> (a -> c a -> c a) -> (s a, c a)

instance Stack StackA where
top = A.top
pop = A.pop
push = A.push
move = A.move

instance Stack StackB where
top = B.top
pop = B.pop
push = B.push
move = B.move
```

```move (Cons 1 Nil) [] A.push
→ (Nil,)
move  Nil B.push
→ ([],Cons 1 Nil)
```