 	return (100 * occur) / st.maxSuccessTests
 }
 
-internal func success(st : State) {
+internal func printDistributionGraph(st : State) {
 	func showP(n : Int) -> String {
 		return (n < 10 ? " " : "") + "\(n)" + "% "
 	}

	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), ==)
