public CachedSequence <T> Reverse()
        {
            CachedSequence <T> newHead = new CachedSequence <T>(Head);
            CachedSequence <T> t       = Tail;

            while (t != null)
            {
                newHead = new CachedSequence <T>(t.Head, newHead);
                t       = t.Tail;
            }
            return(newHead);
        }
        public T ElementAt(int index)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException("index");
            }
            CachedSequence <T> c = this;

            while (--index >= 0)
            {
                c = c.Tail;
                if (c == null)
                {
                    throw new ArgumentOutOfRangeException("index", "`index` is larger than the collection size.");
                }
            }
            return(c.Head);
        }
        public CachedSequence <T> Append(T value)
        {
            CachedSequence <T> start, c;

            start = c = new CachedSequence <T>(Head);

            CachedSequence <T> end = Tail;

            while (end != null)
            {
                var n = new CachedSequence <T>(end.Head);
                c.rest = Either(n);
                c      = n;
                end    = end.Tail;
            }
            c.rest = Either(new CachedSequence <T>(value));

            return(start);
        }
 private Either <CachedSequence <T>, IEnumerator <T> > Either(CachedSequence <T> tail)
 {
     return(Either <CachedSequence <T>, IEnumerator <T> > .A(tail));
 }
 public CachedSequence(T head, CachedSequence <T> tail)
 {
     this.head = head;
     this.rest = tail == null ? null : Either(tail);
 }