 internal func doneTesting(st : State)(f : (StdGen -> Int -> Prop)) -> Result {
 	if st.expectedFailure {
 		println("*** Passed " + "\(st.numSuccessTests)" + " tests")
-		success(st)
+		printDistributionGraph(st)
 		return Result.Success(numTests: st.numSuccessTests, labels: summary(st), output: "")
 	} else {
-		success(st)
+		printDistributionGraph(st)
 		return Result.NoExpectedFailure(numTests: st.numSuccessTests, labels: summary(st), output: "")
 	}
 }
 
 internal func giveUp(st: State)(f : (StdGen -> Int -> Prop)) -> Result {
-	success(st)
+	printDistributionGraph(st)
 	return Result.GaveUp(numTests: st.numSuccessTests, labels: summary(st), output: "")
 }
 
 internal func foundFailure(st : State, res : TestResult, ts : [Rose<TestResult>]) -> (Int, Int, Int) {
-	let st2 = State(name: st.name,
-		maxSuccessTests: st.maxSuccessTests,
-		maxDiscardedTests: st.maxDiscardedTests,
-		computeSize: st.computeSize,
-		numSuccessTests: st.numSuccessTests,
-		numDiscardedTests: st.numDiscardedTests,
-		labels: st.labels,
-		collected: st.collected,
-		expectedFailure: st.expectedFailure,
-		randomSeed: st.randomSeed,
-		numSuccessShrinks: st.numSuccessShrinks,
-		numTryShrinks: st.numTryShrinks + 1,
-		numTotTryShrinks: st.numTotTryShrinks)
-	return localMin(st2, res, res, ts)
-}
-
+	let state = State(name: st.name
+					, maxSuccessTests: st.maxSuccessTests
+					, maxDiscardedTests: st.maxDiscardedTests
+					, computeSize: st.computeSize
+					, numSuccessTests: st.numSuccessTests
+					, numDiscardedTests: st.numDiscardedTests
+					, labels: st.labels
+					, collected: st.collected
+					, expectedFailure: st.expectedFailure
+					, randomSeed: st.randomSeed
+					, numSuccessShrinks: st.numSuccessShrinks
+					, numTryShrinks: st.numTryShrinks + 1
+					, numTotTryShrinks: st.numTotTryShrinks)
+	return localMin(state, res, res, ts)
+}
+
+// Interface to shrinking loop.  Returns (number of shrinks performed, number of failed shrinks, 
+// total number of shrinks performed).
 internal func localMin(st : State, res : TestResult, res2 : TestResult, ts : [Rose<TestResult>]) -> (Int, Int, Int) {
 	if let e = res2.theException {
 		fatalError("Test failed due to exception: \(e)")

	return localMinimum(st, res, ts)
}

internal func dispatchAfterTestCallbacks(st : State, res : TestResult) {
	let _ : [()] = res.callbacks.map({ c in
		switch c {
			case let .AfterTest(_, f):
				f(st, res)
			default:
				return
		}
	})
}

internal func callbackAfterFinalFailure(st : State, res : TestResult) {
	let _ : [()] = res.callbacks.map({ c in
		switch c {
		case let .AfterFinalFailure(_, f):
			f(st, res)
		default:
			return
		}
	})
}

internal func localMinimum(st : State, res : TestResult, ts : [Rose<TestResult>]) -> (Int, Int, Int) {
	if ts.isEmpty {
		return localMinFound(st, res)
	}
	let rose = reduce(ts[0])
	switch rose {
	case .IORose(_):
		fatalError("Rose should not have reduced to IO")
	case .MkRose(let res1, let ts1):
		dispatchAfterTestCallbacks(st, res1())
		if res1().ok == .Some(false) {
			let sta = State(name: st.name,
				maxSuccessTests: st.maxSuccessTests,
				maxDiscardedTests: st.maxDiscardedTests,
				computeSize: st.computeSize,
				numSuccessTests: st.numSuccessTests + 1,
				numDiscardedTests: st.numDiscardedTests,
				labels: st.labels,
				collected: st.collected,
				expectedFailure: st.expectedFailure,
				randomSeed: st.randomSeed,
				numSuccessShrinks: st.numSuccessShrinks,
				numTryShrinks: 0,
				numTotTryShrinks: st.numTotTryShrinks)
			return localMin(sta, res1(), res, ts1())
		} else {
			let sta = State(name: st.name,
				maxSuccessTests: st.maxSuccessTests,
				maxDiscardedTests: st.maxDiscardedTests,
				computeSize: st.computeSize,
				numSuccessTests: st.numSuccessTests + 1,
				numDiscardedTests: st.numDiscardedTests,
				labels: st.labels,
				collected: st.collected,
				expectedFailure: st.expectedFailure,
				randomSeed: st.randomSeed,
				numSuccessShrinks: st.numSuccessShrinks,
				numTryShrinks: st.numTryShrinks,
				numTotTryShrinks: st.numTotTryShrinks + 1)
			return localMin(sta, res, res, Array(ts[1..<ts.count]))
		}
	}
}


	
	println("Proposition: " + st.name)
	println(res.reason + pluralize(testMsg, st.numSuccessTests) + pluralize(shrinkMsg, st.numSuccessShrinks) + "):")
	dispatchAfterFinalFailureCallbacks(st, res)
	return (st.numSuccessShrinks, st.numTotTryShrinks - st.numTryShrinks, st.numTryShrinks)
}

internal func dispatchAfterTestCallbacks(st : State, res : TestResult) {
	for c in res.callbacks {
		switch c {
		case let .AfterTest(_, f):
			f(st, res)
		default:
			return
		}
	}
}

internal func dispatchAfterFinalFailureCallbacks(st : State, res : TestResult) {
	for c in res.callbacks {
		switch c {
		case let .AfterFinalFailure(_, f):
			f(st, res)
		default:
			return
		}
	}
}

internal func summary(s : State) -> [(String, Int)] {
	let strings = s.collected.map({ l in Array(l).map({ "," + $0.0 }).filter({ !$0.isEmpty }) }).reduce([], combine: +)
	let l =  groupBy(sorted(strings), ==)
