private void assertPurityForInput <Tin, Tout>(Func <Tin, Tout> func, Tin input, bool isPure)
            where Tout : IEquatable <Tout>
        {
            var funcMemoized = CategoryTheoryForProgrammers.Memoize(func);

            Assert.True(funcMemoized(input).Equals(func(input)) == isPure);
            Assert.True(funcMemoized(input).Equals(func(input)) == isPure);
        }
        public void MemoizeRandomDoesNotWork()
        {
            Func <int, double> random = (int _) => { var rand = new Random(); return(rand.NextDouble()); };
            var randomMemoized        = CategoryTheoryForProgrammers.Memoize(random);

            Assert.True(randomMemoized(42) != random(42));
            Assert.True(randomMemoized(42) != random(42));
        }
        public void MemoizeRandomSeededWorks()
        {
            Func <int, double> randomSeeded = (int seed) => { var rand = new Random(seed); return(rand.NextDouble()); };
            var randomSeededMemoized        = CategoryTheoryForProgrammers.Memoize(randomSeeded);

            Assert.True(randomSeededMemoized(42) == randomSeeded(42));
            Assert.True(randomSeededMemoized(42) == randomSeeded(42));
        }
        public void MemoizeWorks()
        {
            Func <int, int> addOneLongRunning         = (int a) => { Thread.Sleep(50); return(a++); };
            var             addOneLongRunningMemoized = CategoryTheoryForProgrammers.Memoize(addOneLongRunning);
            var             time = DateTime.Now;

            Console.WriteLine(time);
            Assert.True(addOneLongRunning(42) == addOneLongRunning(42));
            var runtimeOne = (DateTime.Now - time);

            time = DateTime.Now;
            Assert.True(addOneLongRunning(42) == addOneLongRunning(42));
            var runtimeTwo = (DateTime.Now - time);

            Assert.True(runtimeTwo < runtimeOne);
        }