package monads;

import static org.junit.Assert.assertEquals;
import static monads.Stack.*;
import static monads.Pair.*;

import org.junit.Test;

public class StackTest {
	
	private static final Object A = new Object();
	private static final Object B = new Object();

	private Pair pair = pair(empty());

	@Test public void
	starts_empty() {
		assertEquals(empty(), pair.stack);
	}
	
	@Test(expected = Exception.class) public void
	forbids_pop_when_empty() {
		pop(pair.stack);
	}
	
	private static interface StackFunction {
		Pair eval(Stack stack);
	}
	private static class StackPush implements StackFunction {
		private Object value;

		public StackPush(Object value) {
			this.value = value;
		}

		public Pair eval(Stack stack) {
			return push(stack, value);
		}
	}
	private static class StackPop implements StackFunction {
		public Pair eval(Stack stack) {
			return pop(stack);
		}
	}
	
	@Test public void
	pushes_and_pops_an_objects() {	
		pair = new StackPush(A).eval(pair.stack);
		pair = new StackPop().eval(pair.stack);

		assertEquals(A, pair.value);
		assertEquals(empty(), pair.stack);
	}
	
	@Test public void
	pops_objects_in_reverse_push_order() {
		pair = push(pair.stack, A);
		pair = push(pair.stack, B);
		
		pair = pop(pair.stack);
		assertEquals(B, pair.value);

		pair = pop(pair.stack);
		assertEquals(A, pair.value);

		assertEquals(empty(), pair.stack);
	}
}

@@ -454,16 +454,22 @@
 y() %7B%0A%09%09
+Stack.
 pop(pair
@@ -744,16 +744,22 @@
 %09return 
+Stack.
 push(sta
@@ -773,24 +773,100 @@
 ue);%0A%09%09%7D%0A%09%7D%0A
+%09private StackPush push(Object value) %7B%0A%09%09return new StackPush(value);%0A%09%7D%0A%09%0A
 %09private sta
@@ -955,16 +955,22 @@
 %09return 
+Stack.
 pop(stac
@@ -976,24 +976,78 @@
 ck);%0A%09%09%7D%0A%09%7D%0A
+%09private StackPop pop() %7B%0A%09%09return new StackPop();%0A%09%7D%0A
 %09%0A%09@Test pub
@@ -1097,26 +1097,17 @@
 %09pair = 
-new StackP
+p
 ush(A).e
@@ -1132,26 +1132,17 @@
 %09pair = 
-new StackP
+p
 op().eva
@@ -1224,25 +1224,24 @@
 .stack);%0A%09%7D%0A
-%09
 %0A%09@Test publ
@@ -1294,32 +1294,40 @@
 %7B%0A%09%09pair = push(
+A).eval(
 pair.stack, A);%0A
@@ -1324,11 +1324,8 @@
 tack
-, A
 );%0A%09
@@ -1337,16 +1337,24 @@
  = push(
+B).eval(
 pair.sta
@@ -1359,11 +1359,8 @@
 tack
-, B
 );%0A%09
@@ -1366,32 +1366,39 @@
 %09%09%0A%09%09pair = pop(
+).eval(
 pair.stack);%0A%09%09a
@@ -1435,24 +1435,31 @@
 %09pair = pop(
+).eval(
 pair.stack);

Use the Stack function objects all over the place