package fj.data; import fj.Equal; import fj.F0; import fj.F3; import fj.Hash; import fj.Show; import fj.F; import fj.F2; import fj.Function; import fj.Monoid; import fj.Ord; import fj.P; import fj.P1; import fj.P2; import fj.Unit; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.Ordering; import fj.function.Effect1; import java.util.*; import static fj.Bottom.error; import static fj.Function.*; import static fj.P.p; import static fj.P.p2; import static fj.P.weakMemo; import static fj.Unit.unit; import static fj.control.parallel.Promise.promise; import static fj.data.Array.mkArray; import static fj.data.Option.none; import static fj.data.Option.some; import static fj.function.Booleans.not; import static fj.Ordering.EQ; import static fj.Ordering.GT; import static fj.Ordering.LT; /** * A lazy (not yet evaluated), immutable, singly linked list. * * @version %build.number% */ public abstract class Stream<A> implements Iterable<A> { private Stream() { } /** * Returns an iterator for this stream. This method exists to permit the use in a <code>for</code>-each loop. * * @return A iterator for this stream. */ public final Iterator<A> iterator() { return toCollection().iterator(); } /** * The first element of the stream or fails for the empty stream. * * @return The first element of the stream or fails for the empty stream. */ public abstract A head(); /** * The stream without the first element or fails for the empty stream. * * @return The stream without the first element or fails for the empty stream. */ public abstract P1<Stream<A>> tail(); /** * Returns <code>true</code> if this stream is empty, <code>false</code> otherwise. * * @return <code>true</code> if this stream is empty, <code>false</code> otherwise. */ public final boolean isEmpty() { return this instanceof Nil; } /** * Returns <code>false</code> if this stream is empty, <code>true</code> otherwise. * * @return <code>false</code> if this stream is empty, <code>true</code> otherwise. */ public final boolean isNotEmpty() { return this instanceof Cons; } /** * Performs a reduction on this stream using the given arguments. Equivalent to {@link #uncons}. * * @deprecated As of release 4.5, use {@link #uncons} * * @param nil The value to return if this stream is empty. * @param cons The function to apply to the head and tail of this stream if it is not empty. * @return A reduction on this stream. */ @Deprecated public final <B> B stream(final B nil, final F<A, F<P1<Stream<A>>, B>> cons) { return uncons(nil, cons); } /** * Performs a reduction on this stream using the given arguments. * * @param nil The value to return if this stream is empty. * @param cons The function to apply to the head and tail of this stream if it is not empty. * @return A reduction on this stream. */ public final <B> B uncons(final B nil, final F<A, F<P1<Stream<A>>, B>> cons) { return isEmpty() ? nil : cons.f(head()).f(tail()); } /** * Performs a right-fold reduction across this stream. This function uses O(length) stack space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the right-fold reduction. */ public final <B> B foldRight(final F<A, F<P1<B>, B>> f, final B b) { return foldRight(uncurryF2(f), b); } /** * Performs a right-fold reduction across this stream. This function uses O(length) stack space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the right-fold reduction. */ public final <B> B foldRight(final F2<A, P1<B>, B> f, final B b) { return isEmpty() ? b : f.f(head(), P.lazy(() -> tail()._1().foldRight(f, b))); } /** * Performs a right-fold reduction across this stream. This function uses O(length) stack space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the right-fold reduction. */ public final <B> B foldRight1(final F<A, F<B, B>> f, final B b) { return foldRight1(uncurryF2(f), b); } /** * Performs a right-fold reduction across this stream. This function uses O(length) stack space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the right-fold reduction. */ public final <B> B foldRight1(final F2<A, B, B> f, final B b) { return isEmpty() ? b : f.f(head(), tail()._1().foldRight1(f, b)); } /** * Performs a left-fold reduction across this stream. This function runs in constant space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the left-fold reduction. */ public final <B> B foldLeft(final F<B, F<A, B>> f, final B b) { return foldLeft(uncurryF2(f), b); } /** * Performs a left-fold reduction across this stream. This function runs in constant space. * * @param f The function to apply on each element of the stream. * @param b The beginning value to start the application from. * @return The final result after the left-fold reduction. */ public final <B> B foldLeft(final F2<B, A, B> f, final B b) { B x = b; for (Stream<A> xs = this; !xs.isEmpty(); xs = xs.tail()._1()) x = f.f(x, xs.head()); return x; } /** * Takes the first 2 elements of the stream and applies the function to them, * then applies the function to the result and the third element and so on. * * @param f The function to apply on each element of the stream. * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F2<A, A, A> f) { if (isEmpty()) throw error("Undefined: foldLeft1 on empty list"); return tail()._1().foldLeft(f, head()); } /** * Takes the first 2 elements of the stream and applies the function to them, * then applies the function to the result and the third element and so on. * * @param f The function to apply on each element of the stream. * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F<A, F<A, A>> f) { return foldLeft1(uncurryF2(f)); } /** * Returns the head of this stream if there is one or the given argument if this stream is empty. * * @param a The argument to return if this stream is empty. * @return The head of this stream if there is one or the given argument if this stream is empty. */ public final A orHead(final F0<A> a) { return isEmpty() ? a.f() : head(); } /** * Returns the tail of this stream if there is one or the given argument if this stream is empty. * * @param as The argument to return if this stream is empty. * @return The tail of this stream if there is one or the given argument if this stream is empty. */ public final P1<Stream<A>> orTail(final F0<Stream<A>> as) { return isEmpty() ? P.lazy(as) : tail(); } /** * Intersperses the given value between each two elements of the stream. * * @param a The value to intersperse between values of the stream. * @return A new stream with the given value between each two elements of the stream. */ public final Stream<A> intersperse(final A a) { return isEmpty() ? this : cons(head(), new P1<Stream<A>>() { public Stream<A> _1() { return prefix(a, tail()._1()); } public Stream<A> prefix(final A x, final Stream<A> xs) { return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), () -> prefix(a, xs.tail()._1())))); } }); } /** * Maps the given function across this stream. * * @param f The function to map across this stream. * @return A new stream after the given function has been applied to each element. */ public final <B> Stream<B> map(final F<A, B> f) { return isEmpty() ? Stream.nil() : cons(f.f(head()), () -> tail()._1().map(f)); } /** * Provides a first-class version of the map function. * * @return A function that maps a given function across a given stream. */ public static <A, B> F<F<A, B>, F<Stream<A>, Stream<B>>> map_() { return f -> as -> as.map(f); } /** * Performs a side-effect for each element of this stream. * * @param f The side-effect to perform for the given element. * @return The unit value. */ public final Unit foreach(final F<A, Unit> f) { for (Stream<A> xs = this; xs.isNotEmpty(); xs = xs.tail()._1()) f.f(xs.head()); return unit(); } /** * Performs a side-effect for each element of this stream. * * @param f The side-effect to perform for the given element. */ public final void foreachDoEffect(final Effect1<A> f) { for (Stream<A> xs = this; xs.isNotEmpty(); xs = xs.tail()._1()) f.f(xs.head()); } /** * Filters elements from this stream by returning only elements which produce <code>true</code> * when the given function is applied to them. * * @param f The predicate function to filter on. * @return A new stream whose elements all match the given predicate. */ public final Stream<A> filter(final F<A, Boolean> f) { final Stream<A> as = dropWhile(not(f)); return as.isNotEmpty() ? cons(as.head(), () -> as.tail()._1().filter(f)) : as; } /** * Appends the given stream to this stream. * * @param as The stream to append to this one. * @return A new stream that has appended the given stream. */ public final Stream<A> append(final Stream<A> as) { return isEmpty() ? as : cons(head(), () -> tail()._1().append(as)); } /** * Appends the given stream to this stream. * * @param as The stream to append to this one. * @return A new stream that has appended the given stream. */ public final Stream<A> append(final F0<Stream<A>> as) { return isEmpty() ? as.f() : cons(head(), () -> tail()._1().append(as)); } /** * Returns a new stream of all the items in this stream that do not appear in the given stream. * * @param eq an equality for the items of the streams. * @param xs a list to subtract from this stream. * @return a stream of all the items in this stream that do not appear in the given stream. */ public final Stream<A> minus(final Equal<A> eq, final Stream<A> xs) { return removeAll(compose(Monoid.disjunctionMonoid.sumLeftS(), xs.mapM(curry(eq.eq())))); } /** * Filters elements from this stream by returning only elements which produce <code>false</code> when * the given function is applied to them. * * @param f The predicate function to filter on. * @return A new stream whose elements do not match the given predicate. */ public final Stream<A> removeAll(final F<A, Boolean> f) { return filter(compose(not, f)); } /** * Turn a stream of functions into a function returning a stream. * * @param fs The stream of functions to sequence into a single function that returns a stream. * @return A function that, when given an argument, applies all the functions in the given stream to it * and returns a stream of the results. */ public static <A, B> F<B, Stream<A>> sequence_(final Stream<F<B, A>> fs) { return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), curry((a, stream) -> cons(a, p(stream)))), Function .constant(Stream.nil())); } /** * Maps the given function of arity-2 across this stream and returns a function that applies all the resulting * functions to a given argument. * * @param f A function of arity-2 * @return A function that, when given an argument, applies the given function to that argument and every element * in this list. */ public final <B, C> F<B, Stream<C>> mapM(final F<A, F<B, C>> f) { return sequence_(map(f)); } /** * Binds the given function across each element of this stream with a final join. * * @param f The function to apply to each element of this stream. * @return A new stream after performing the map, then final join. */ public final <B> Stream<B> bind(final F<A, Stream<B>> f) { return foldRight(h -> t -> f.f(h).append(t), nil()); } /** * Binds the given function across each element of this stream and the given stream with a final * join. * * @param sb A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given stream. * @return A new stream after performing the map, then final join. */ public final <B, C> Stream<C> bind(final Stream<B> sb, final F<A, F<B, C>> f) { return sb.apply(map(f)); } /** * Binds the given function across each element of this stream and the given stream with a final * join. * * @param sb A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given stream. * @return A new stream after performing the map, then final join. */ public final <B, C> Stream<C> bind(final Stream<B> sb, final F2<A, B, C> f) { return bind(sb, curry(f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D> Stream<D> bind(final Stream<B> sb, final Stream<C> sc, final F<A, F<B, F<C, D>>> f) { return sc.apply(bind(sb, f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param sd A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D, E> Stream<E> bind(final Stream<B> sb, final Stream<C> sc, final Stream<D> sd, final F<A, F<B, F<C, F<D, E>>>> f) { return sd.apply(bind(sb, sc, f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param sd A given stream to bind the given function with. * @param se A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D, E, F$> Stream<F$> bind(final Stream<B> sb, final Stream<C> sc, final Stream<D> sd, final Stream<E> se, final F<A, F<B, F<C, F<D, F<E, F$>>>>> f) { return se.apply(bind(sb, sc, sd, f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param sd A given stream to bind the given function with. * @param se A given stream to bind the given function with. * @param sf A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D, E, F$, G> Stream<G> bind(final Stream<B> sb, final Stream<C> sc, final Stream<D> sd, final Stream<E> se, final Stream<F$> sf, final F<A, F<B, F<C, F<D, F<E, F<F$, G>>>>>> f) { return sf.apply(bind(sb, sc, sd, se, f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param sd A given stream to bind the given function with. * @param se A given stream to bind the given function with. * @param sf A given stream to bind the given function with. * @param sg A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D, E, F$, G, H> Stream<H> bind(final Stream<B> sb, final Stream<C> sc, final Stream<D> sd, final Stream<E> se, final Stream<F$> sf, final Stream<G> sg, final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, H>>>>>>> f) { return sg.apply(bind(sb, sc, sd, se, sf, f)); } /** * Binds the given function across each element of this stream and the given streams with a final * join. * * @param sb A given stream to bind the given function with. * @param sc A given stream to bind the given function with. * @param sd A given stream to bind the given function with. * @param se A given stream to bind the given function with. * @param sf A given stream to bind the given function with. * @param sg A given stream to bind the given function with. * @param sh A given stream to bind the given function with. * @param f The function to apply to each element of this stream and the given streams. * @return A new stream after performing the map, then final join. */ public final <B, C, D, E, F$, G, H, I> Stream<I> bind(final Stream<B> sb, final Stream<C> sc, final Stream<D> sd, final Stream<E> se, final Stream<F$> sf, final Stream<G> sg, final Stream<H> sh, final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, F<H, I>>>>>>>> f) { return sh.apply(bind(sb, sc, sd, se, sf, sg, f)); } /** * Performs a bind across each stream element, but ignores the element value each time. * * @param bs The stream to apply in the final join. * @return A new stream after the final join. */ public final <B> Stream<B> sequence(final Stream<B> bs) { final F<A, Stream<B>> c = constant(bs); return bind(c); } /** * Sequence through the Stream monad. * * @param io The IO stream to sequence. * @return The stream of IOs after sequencing. */ public static <A> Stream<IO<A>> sequence(final IO<Stream<A>> io) { return IOFunctions.runSafe(io).map(IOFunctions::unit); } /** * Sequence through the Stream monad. * * @param p The lazy stream to sequence. * @return The stream of (pre-calculated) lazy values after sequencing. */ public static <A> Stream<P1<A>> sequence(final F0<Stream<A>> p) { return p.f().map(P::p); } /** * Sequence through the Stream monad. * * @param o The optional stream to sequence. * @return The stream of options after sequencing. */ public static <A> Stream<Option<A>> sequence(final Option<Stream<A>> o) { return o.isNone() ? nil() : o.some().map(Option::some); } /** * Performs function application within a stream (applicative functor pattern). * * @param sf The stream of functions to apply. * @return A new stream after applying the given stream of functions through this stream. */ public final <B> Stream<B> apply(final Stream<F<A, B>> sf) { return sf.bind(this::map); } /** * Interleaves the given stream with this stream to produce a new stream. * * @param as The stream to interleave this stream with. * @return A new stream with elements interleaved from this stream and the given stream. */ public final Stream<A> interleave(final Stream<A> as) { return isEmpty() ? as : as.isEmpty() ? this : cons(head(), () -> as.interleave(tail()._1())); } public static <A> Stream<A> enumerationStream(Enumeration<A> e) { if (e.hasMoreElements()) { return cons(e.nextElement(), () -> enumerationStream(e)); } else { return nil(); } } /** * Sort this stream according to the given ordering. * * @param o An ordering for the elements of this stream. * @return A new stream with the elements of this stream sorted according to the given ordering. */ public final Stream<A> sort(final Ord<A> o) { return mergesort(o, map(flip(Stream.<A>cons()).f(p(Stream.nil())))); } // Merges a stream of individually sorted streams into a single sorted stream. private static <A> Stream<A> mergesort(final Ord<A> o, final Stream<Stream<A>> s) { if (s.isEmpty()) return nil(); Stream<Stream<A>> xss = s; while (xss.tail()._1().isNotEmpty()) xss = mergePairs(o, xss); return xss.head(); } // Merges individually sorted streams two at a time. private static <A> Stream<Stream<A>> mergePairs(final Ord<A> o, final Stream<Stream<A>> s) { if (s.isEmpty() || s.tail()._1().isEmpty()) return s; final Stream<Stream<A>> t = s.tail()._1(); return cons(merge(o, s.head(), t.head()), () -> mergePairs(o, t.tail()._1())); } // Merges two individually sorted streams. private static <A> Stream<A> merge(final Ord<A> o, final Stream<A> xs, final Stream<A> ys) { if (xs.isEmpty()) return ys; if (ys.isEmpty()) return xs; final A x = xs.head(); final A y = ys.head(); if (o.isGreaterThan(x, y)) return cons(y, () -> merge(o, xs, ys.tail()._1())); return cons(x, () -> merge(o, xs.tail()._1(), ys)); } /** * Sort this stream according to the given ordering, using a parallel Quick Sort algorithm that uses the given * parallelisation strategy. * * @param o An ordering for the elements of this stream. * @param s A strategy for parallelising the algorithm. * @return A new stream with the elements of this stream sorted according to the given ordering. */ public final Stream<A> sort(final Ord<A> o, final Strategy<Unit> s) { return qs(o, s).claim(); } private Promise<Stream<A>> qs(final Ord<A> o, final Strategy<Unit> s) { if (isEmpty()) return promise(s, p(this)); else { final F<Boolean, Boolean> id = identity(); final A x = head(); final P1<Stream<A>> xs = tail(); final Promise<Stream<A>> left = Promise.join(s, xs.map(flt(o, s, x, id))); final Promise<Stream<A>> right = xs.map(flt(o, s, x, not))._1(); final Monoid<Stream<A>> m = Monoid.streamMonoid(); return right.fmap(m.sum(single(x))).apply(left.fmap(m.sum())); } } private static <A> F<Stream<A>, Promise<Stream<A>>> qs_(final Ord<A> o, final Strategy<Unit> s) { return xs -> xs.qs(o, s); } private static <A> F<Stream<A>, Promise<Stream<A>>> flt(final Ord<A> o, final Strategy<Unit> s, final A x, final F<Boolean, Boolean> f) { final F<F<A, Boolean>, F<Stream<A>, Stream<A>>> filter = filter(); final F<A, Boolean> lt = o.isLessThan(x); return compose(qs_(o, s), filter.f(compose(f, lt))); } /** * Projects an immutable collection of this stream. * * @return An immutable collection of this stream. */ public final Collection<A> toCollection() { return new AbstractCollection<A>() { public Iterator<A> iterator() { return new Iterator<A>() { private Stream<A> xs = Stream.this; public boolean hasNext() { return xs.isNotEmpty(); } public A next() { if (xs.isEmpty()) throw new NoSuchElementException(); else { final A a = xs.head(); xs = xs.tail()._1(); return a; } } public void remove() { throw new UnsupportedOperationException(); } }; } public int size() { return length(); } }; } /** * Returns a stream of integers from the given <code>from</code> value (inclusive) to the given * <code>to</code> value (exclusive). * * @param from The minimum value for the stream (inclusive). * @param to The maximum value for the stream (exclusive). * @return A stream of integers from the given <code>from</code> value (inclusive) to the given * <code>to</code> value (exclusive). */ public static Stream<Integer> range(final int from, final long to) { return from >= to ? Stream.nil() : cons(from, () -> range(from + 1, to)); } /** * Constructs a stream with the given elements. * * @param as The elements which which to construct a stream. * @return a new stream with the given elements. */ @SafeVarargs public static <A> Stream<A> stream(final A... as) { return arrayStream(as); } /** * Constructs a stream with the given elements in the Iterable. Equivalent to {@link #iterableStream(Iterable)} . * * @deprecated As of release 4.5, use {@link #iterableStream(Iterable)} */ @Deprecated public static <A> Stream<A> stream(Iterable<A> it) { return iterableStream(it); } /** * Constructs a stream with the given elements in the Iterator. Equivalent to {@link #iteratorStream(Iterator)} . * * @deprecated As of release 4.5, use {@link #iteratorStream(Iterator)} */ @Deprecated public static <A> Stream<A> stream(final Iterator<A> it) { return iteratorStream(it); } /** * Constructs a stream with the given elements in the Iterator. */ public static <A> Stream<A> iteratorStream(final Iterator<A> it) { if (it.hasNext()) { final A a = it.next(); return cons(a, () -> iteratorStream(it)); } else return nil(); } /** * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the * given value and stepping at increments of <code>1</code>. * * @param e The enumerator to compute successors from. * @param from The value to begin computing successors from. * @return A stream that is either infinite or bounded up to the maximum value of the given iterator starting at the * given value and stepping at increments of <code>1</code>. */ public static <A> Stream<A> forever(final Enumerator<A> e, final A from) { return forever(e, from, 1L); } /** * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the * given value and stepping at the given increment. * * @param e The enumerator to compute successors from. * @param from The value to begin computing successors from. * @param step The increment to step. * @return A stream that is either infinite or bounded up to the maximum value of the given iterator starting at the * given value and stepping at the given increment. */ public static <A> Stream<A> forever(final Enumerator<A> e, final A from, final long step) { return cons(from, () -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil())); } /** * Returns a stream using the given enumerator from the given value to the other given value stepping at increments of * <code>1</code>. * * @param e The enumerator to compute successors from. * @param from The value to begin computing successors from. * @param to The value to stop computing successors from. * @return A stream using the given enumerator from the given value to the other given value stepping at increments of * <code>1</code>. */ public static <A> Stream<A> range(final Enumerator<A> e, final A from, final A to) { return range(e, from, to, 1L); } /** * Returns a stream using the given enumerator from the given value to the other given value stepping at the given * increment. * * @param e The enumerator to compute successors from. * @param from The value to begin computing successors from. * @param to The value to stop computing successors from. * @param step The increment to step. * @return A stream using the given enumerator from the given value to the other given value stepping at the given * increment. */ public static <A> Stream<A> range(final Enumerator<A> e, final A from, final A to, final long step) { final Ordering o = e.order().compare(from, to); return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, () -> join(e.plus(from, step).filter(a -> !(o == LT ? e.order().isLessThan(to, a) : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream())); } /** * Returns an infinite stream of integers from the given <code>from</code> value (inclusive). * * @param from The minimum value for the stream (inclusive). * @return A stream of integers from the given <code>from</code> value (inclusive). */ public static Stream<Integer> range(final int from) { return cons(from, () -> range(from + 1)); } /** * Returns a first-class version of the filter function. * * @return a function that filters a given stream using a given predicate. */ public static <A> F<F<A, Boolean>, F<Stream<A>, Stream<A>>> filter() { return curry((f, as) -> as.filter(f)); } /** * Zips this stream with the given stream of functions, applying each function in turn to the * corresponding element in this stream to produce a new stream. If this stream and the given stream * have different lengths, then the longer stream is normalised so this function never fails. * * @param fs The stream of functions to apply to this stream. * @return A new stream with a length the same as the shortest of this stream and the given stream. */ public final <B> Stream<B> zapp(final Stream<F<A, B>> fs) { return fs.isEmpty() || isEmpty() ? Stream.nil() : cons(fs.head().f(head()), () -> tail()._1().zapp(fs.tail()._1())); } /** * Zips this stream with the given stream using the given function to produce a new stream. If * this stream and the given stream have different lengths, then the longer stream is normalised * so this function never fails. * * @param bs The stream to zip this stream with. * @param f The function to zip this stream and the given stream with. * @return A new stream with a length the same as the shortest of this stream and the given * stream. */ public final <B, C> Stream<C> zipWith(final Stream<B> bs, final F<A, F<B, C>> f) { return bs.zapp(zapp(repeat(f))); } /** * Zips this stream with the given stream using the given function to produce a new stream. If * this stream and the given stream have different lengths, then the longer stream is normalised * so this function never fails. * * @param bs The stream to zip this stream with. * @param f The function to zip this stream and the given stream with. * @return A new stream with a length the same as the shortest of this stream and the given * stream. */ public final <B, C> Stream<C> zipWith(final Stream<B> bs, final F2<A, B, C> f) { return zipWith(bs, curry(f)); } /** * Partially-applied version of zipWith. * Returns a function that zips a given stream with this stream using the given function. * * @param f The function to zip this stream and a given stream with. * @return A function that zips a given stream with this stream using the given function. */ public final <B, C> F<Stream<B>, Stream<C>> zipWith(final F<A, F<B, C>> f) { return stream -> zipWith(stream, f); } /** * Zips this stream with the given stream to produce a stream of pairs. If this stream and the * given stream have different lengths, then the longer stream is normalised so this function * never fails. * * @param bs The stream to zip this stream with. * @return A new stream with a length the same as the shortest of this stream and the given * stream. */ public final <B> Stream<P2<A, B>> zip(final Stream<B> bs) { final F<A, F<B, P2<A, B>>> __2 = p2(); return zipWith(bs, __2); } /** * Zips this stream with the index of its element as a pair. * * @return A new stream with the same length as this stream. */ public final Stream<P2<A, Integer>> zipIndex() { return zipWith(range(0), (F2<A, Integer, P2<A, Integer>>) P::p); } /** * Returns an either projection of this stream; the given argument in <code>Left</code> if empty, * or the first element in <code>Right</code>. * * @param x The value to return in left if this stream is empty. * @return An either projection of this stream. */ public final <X> Either<X, A> toEither(final F0<X> x) { return isEmpty() ? Either.left(x.f()) : Either.right(head()); } /** * Returns an option projection of this stream; <code>None</code> if empty, or the first element * in <code>Some</code>. * * @return An option projection of this stream. */ public final Option<A> toOption() { return isEmpty() ? Option.none() : some(head()); } /** * To be removed in future release: * affectation of the result of this method to a non generic array * will result in runtime error (ClassCastException). * * @deprecated As of release 4.6, use {@link #array(Class)}. */ @Deprecated public final A[] toJavaArray() { @SuppressWarnings("unchecked") final A[] array = (A[]) new Object[length()]; int i = 0; for (A a: this) { array[i] = a; i++; } return array; } /** * Returns a list projection of this stream. * * @return A list projection of this stream. */ public final List<A> toList() { List.Buffer<A> buf = List.Buffer.empty(); foreachDoEffect(buf::snoc); return buf.toList(); } /** * Returns a java.util.List projection of this stream. */ public final java.util.List<A> toJavaList() { return new java.util.LinkedList<>(toCollection()); } /** * Returns a array projection of this stream. * * @return A array projection of this stream. */ @SuppressWarnings("unchecked") public final Array<A> toArray() { final int l = length(); final Object[] a = new Object[l]; Stream<A> x = this; for (int i = 0; i < l; i++) { a[i] = x.head(); x = x.tail()._1(); } return mkArray(a); } /** * Returns a array projection of this stream. * * @param c The class type of the array to return. * @return A array projection of this stream. */ @SuppressWarnings({"unchecked", "UnnecessaryFullyQualifiedName"}) public final Array<A> toArray(final Class<A[]> c) { final A[] a = (A[]) java.lang.reflect.Array.newInstance(c.getComponentType(), length()); int i = 0; for (final A x : this) { a[i] = x; i++; } return Array.array(a); } /** * Returns an array from this stream. * * @param c The class type of the array to return. * @return An array from this stream. */ public final A[] array(final Class<A[]> c) { return toArray(c).array(c); } /** * Prepends (cons) the given element to this stream to product a new stream. * * @param a The element to prepend. * @return A new stream with the given element at the head. */ public final Stream<A> cons(final A a) { return new Cons<>(a, () -> Stream.this); } /** * Returns a string from the given stream of characters. The inverse of this function is {@link * #fromString(String)}. * * @param cs The stream of characters to produce the string from. * @return A string from the given stream of characters. */ public static String asString(final Stream<Character> cs) { StringBuilder sb = new StringBuilder(); cs.foreachDoEffect(sb::append); return sb.toString(); } /** * Returns a stream of characters from the given string. The inverse of this function is {@link * #asString(Stream)}. * * @param s The string to produce the stream of characters from. * @return A stream of characters from the given string. */ public static Stream<Character> fromString(final String s) { return LazyString.str(s).toStream(); } /** * Append the given element to this stream to product a new stream. * * @param a The element to append. * @return A new stream with the given element at the end. */ public final Stream<A> snoc(final A a) { return snoc(p(a)); } /** * Append the given element to this stream to produce a new stream. * * @param a The element to append. * @return A new stream with the given element at the end. */ public final Stream<A> snoc(final F0<A> a) { return append(() -> single(a.f())); } /** * Returns the first <code>n</code> elements from the head of this stream. * * @param n The number of elements to take from this stream. * @return The first <code>n</code> elements from the head of this stream. */ public final Stream<A> take(final int n) { return n <= 0 || isEmpty() ? Stream.nil() : cons(head(), () -> n <= 1 ? Stream.nil() : tail()._1().take(n - 1)); } /** * Drops the given number of elements from the head of this stream if they are available. * * @param i The number of elements to drop from the head of this stream. * @return A stream with a length the same, or less than, this stream. */ public final Stream<A> drop(final int i) { Stream<A> xs = this; for (int c = 0; xs.isNotEmpty() && c < i; xs = xs.tail()._1()) c++; return xs; } /** * Returns the first elements of the head of this stream that match the given predicate function. * * @param f The predicate function to apply on this stream until it finds an element that does not * hold, or the stream is exhausted. * @return The first elements of the head of this stream that match the given predicate function. */ public final Stream<A> takeWhile(final F<A, Boolean> f) { return isEmpty() ? this : f.f(head()) ? cons(head(), () -> tail()._1().takeWhile(f)) : Stream.nil(); } /** * Traversable instance of Stream for IO. * * @return traversed value */ public final <B> IO<Stream<B>> traverseIO(F<A, IO<B>> f) { return this.foldRight1((a, acc) -> IOFunctions.bind(acc, (Stream<B> bs) -> IOFunctions.map(f.f(a), bs::cons)), IOFunctions.unit(Stream.nil())); } /** * Traversable instance of Stream for Option. * * @return traversed value */ public final <B> Option<Stream<B>> traverseOption(F<A, Option<B>> f) { return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(bs::cons)), some(Stream.nil())); } /** * Removes elements from the head of this stream that do not match the given predicate function * until an element is found that does match or the stream is exhausted. * * @param f The predicate function to apply through this stream. * @return The stream whose first element does not match the given predicate function. */ public final Stream<A> dropWhile(final F<A, Boolean> f) { Stream<A> as; //noinspection StatementWithEmptyBody for (as = this; !as.isEmpty() && f.f(as.head()); as = as.tail()._1()) ; return as; } /** * Returns a tuple where the first element is the longest prefix of this stream that satisfies * the given predicate and the second element is the remainder of the stream. * * @param p A predicate to be satisfied by a prefix of this stream. * @return A tuple where the first element is the longest prefix of this stream that satisfies * the given predicate and the second element is the remainder of the stream. */ public final P2<Stream<A>, Stream<A>> span(final F<A, Boolean> p) { if (isEmpty()) return p(this, this); else if (p.f(head())) { final P1<P2<Stream<A>, Stream<A>>> yszs = P.lazy(() -> tail()._1().span(p)); return P.lazy( () -> cons(head(), yszs.map(P2.__1())), () -> yszs._1()._2() ); } else return p(Stream.nil(), this); } /** * Returns a new stream resulting from replacing all elements that match the given predicate with the given element. * * @param p The predicate to match replaced elements. * @param a The element with which to replace elements. * @return A new stream resulting from replacing all elements that match the given predicate with the given element. */ public final Stream<A> replace(final F<A, Boolean> p, final A a) { if (isEmpty()) return nil(); else { final P2<Stream<A>, Stream<A>> s = span(p); return s._1().append(cons(a, () -> s._2().tail()._1().replace(p, a))); } } /** * Returns a tuple where the first element is the longest prefix of this stream that does not satisfy * the given predicate and the second element is the remainder of the stream. * * @param p A predicate not to be satisfied by a prefix of this stream. * @return A tuple where the first element is the longest prefix of this stream that does not satisfy * the given predicate and the second element is the remainder of the stream. */ public final P2<Stream<A>, Stream<A>> split(final F<A, Boolean> p) { return span(compose(not, p)); } /** * Reverse this stream in constant stack space. * * @return A new stream that is the reverse of this one. */ public final Stream<A> reverse() { return foldLeft((as, a) -> cons(a, () -> as), Stream.nil()); } /** * Get the last element of this stream. Undefined for infinite streams. * * @return The last element in this stream, if there is one. */ public final A last() { return reverse().head(); } /** * The length of this stream. This function will not terminate for an infinite stream. * * @return The length of this stream. */ public final int length() { // we're using an iterative approach here as the previous implementation (toList().length()) took // very long even for some 10000 elements. Stream<A> xs = this; int i = 0; while (!xs.isEmpty()) { xs = xs.tail()._1(); i += 1; } return i; } /** * Returns the element at the given index if it exists, fails otherwise. * * @param i The index at which to get the element to return. * @return The element at the given index if it exists, fails otherwise. */ public final A index(final int i) { if (i < 0) throw error("index " + i + " out of range on stream"); else { Stream<A> xs = this; for (int c = 0; c < i; c++) { if (xs.isEmpty()) throw error("index " + i + " out of range on stream"); xs = xs.tail()._1(); } if (xs.isEmpty()) throw error("index " + i + " out of range on stream"); return xs.head(); } } /** * Returns <code>true</code> if the predicate holds for all of the elements of this stream, * <code>false</code> otherwise (<code>true</code> for the empty stream). * * @param f the predicate function to test on each element of this stream. * @return <code>true</code> if the predicate holds for all of the elements of this stream, * <code>false</code> otherwise. */ public final boolean forall(final F<A, Boolean> f) { for (final A a : this) { if (!f.f(a)) return false; } return true; } @Override public final boolean equals(Object other) { return Equal.equals0(Stream.class, this, other, () -> Equal.streamEqual(Equal.anyEqual())); } @Override public final int hashCode() { return Hash.streamHash(Hash.<A>anyHash()).hash(this); } @Override public final String toString() { return toStringLazy(); } public final String toStringLazy() { return isEmpty() ? "Nil()" : "Cons(" + Show.<A>anyShow().showS(head()) + ", ?)"; } public final String toStringEager() { return Show.streamShow(Show.<A>anyShow()).showS(this); } /** * Returns <code>true</code> if the predicate holds for at least one of the elements of this * stream, <code>false</code> otherwise (<code>false</code> for the empty stream). * * @param f The predicate function to test on the elements of this stream. * @return <code>true</code> if the predicate holds for at least one of the elements of this * stream. */ public final boolean exists(final F<A, Boolean> f) { return dropWhile(not(f)).isNotEmpty(); } /** * Finds the first occurrence of an element that matches the given predicate or no value if no * elements match. * * @param f The predicate function to test on elements of this stream. * @return The first occurrence of an element that matches the given predicate or no value if no * elements match. */ public final Option<A> find(final F<A, Boolean> f) { for (Stream<A> as = this; as.isNotEmpty(); as = as.tail()._1()) { if (f.f(as.head())) return some(as.head()); } return none(); } /** * Binds the given function across the stream of substreams of this stream. * * @param k A function to bind across this stream and its substreams. * @return a new stream of the results of applying the given function to this stream and its substreams. */ public final <B> Stream<B> cobind(final F<Stream<A>, B> k) { return substreams().map(k); } /** * Returns a stream of the suffixes of this stream. A stream is considered to be a suffix of itself in this context. * * @return a stream of the suffixes of this stream, starting with the stream itself. */ public final Stream<Stream<A>> tails() { return isEmpty() ? Stream.nil() : cons(this, () -> tail()._1().tails()); } /** * Returns a stream of all prefixes of this stream. A stream is considered a prefix of itself in tnis context. * * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream<Stream<A>> inits() { final Stream<Stream<A>> nil = cons(Stream.nil(), Stream::nil); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.<A>cons_().f(head()))); } /** * Returns a stream of all infixes of this stream. A stream is considered to contain itself. * * @return a stream of the infixes of this stream. */ public final Stream<Stream<A>> substreams() { return tails().bind(Stream::inits); } /** * Returns the position of the first element matching the given predicate, if any. * * @param p A predicate to match. * @return the position of the first element matching the given predicate, if any. */ public final Option<Integer> indexOf(final F<A, Boolean> p) { return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2()); } /** * Applies a stream of comonadic functions to this stream, returning a stream of values. * * @param fs A stream of comonadic functions to apply to this stream. * @return A new stream of the results of applying the stream of functions to this stream. */ public final <B> Stream<B> sequenceW(final Stream<F<Stream<A>, B>> fs) { return fs.isEmpty() ? Stream.nil() : cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } /** * Converts this stream to a function of natural numbers. * * @return A function from natural numbers to values with the corresponding position in this stream. */ public final F<Integer, A> toFunction() { return this::index; } /** * Converts a function of natural numbers to a stream. * * @param f The function to convert to a stream. * @return A new stream of the results of the given function applied to the natural numbers, starting at 0. */ public static <A> Stream<A> fromFunction(final F<Natural, A> f) { return fromFunction(Enumerator.naturalEnumerator, f, Natural.ZERO); } /** * Converts a function of an enumerable type to a stream of the results of that function, * starting at the given index. * * @param e An enumerator for the domain of the function. * @param f The function to convert to a stream. * @param i The index into the function at which to begin the stream. * @return A new stream of the results of the given function applied to the values of the given enumerator, * starting at the given value. */ public static <A, B> Stream<A> fromFunction(final Enumerator<B> e, final F<B, A> f, final B i) { return cons(f.f(i), () -> { final Option<B> s = e.successor(i); return s.isSome() ? fromFunction(e, f, s.some()) : Stream.nil(); }); } /** * Transforms a stream of pairs into a stream of first components and a stream of second components. * * @param xs The stream of pairs to transform. * @return A stream of first components and a stream of second components. */ public static <A, B> P2<Stream<A>, Stream<B>> unzip(final Stream<P2<A, B>> xs) { return xs.foldRight((p, ps) -> { final P2<Stream<A>, Stream<B>> pp = ps._1(); return p(cons(p._1(), p(pp._1())), cons(p._2(), p(pp._2()))); }, p(Stream.nil(), Stream.nil())); } /** * A first-class version of the zipWith function. * * @return a function that zips two given streams with a given function. */ public static <A, B, C> F<Stream<A>, F<Stream<B>, F<F<A, F<B, C>>, Stream<C>>>> zipWith() { return curry((F3<Stream<A>, Stream<B>, F<A, F<B, C>>, Stream<C>>) Stream::zipWith); } private static final class Nil<A> extends Stream<A> { public A head() { throw error("head on empty stream"); } public P1<Stream<A>> tail() { throw error("tail on empty stream"); } } private static final class Cons<A> extends Stream<A> { private final A head; private final P1<Stream<A>> tail; Cons(final A head, final F0<Stream<A>> tail) { this.head = head; this.tail = weakMemo(tail); } public A head() { return head; } public P1<Stream<A>> tail() { return tail; } } /** * Returns a function that prepends (cons) an element to a stream to produce a new stream. * * @return A function that prepends (cons) an element to a stream to produce a new stream. */ public static <A> F<A, F<P1<Stream<A>>, Stream<A>>> cons() { return a -> list -> cons(a, list); } /** * Returns a function that prepends (cons) an element to a stream to produce a new stream. * * @return A function that prepends (cons) an element to a stream to produce a new stream. */ public static <A> F<A, F<Stream<A>, Stream<A>>> cons_() { return curry((a, as) -> as.cons(a)); } /** * Returns an empty stream. * * @return An empty stream. */ public static <A> Stream<A> nil() { return new Nil<>(); } /** * Returns an empty stream. * * @return An empty stream. */ public static <A> P1<Stream<A>> nil_() { return P.lazy(Nil::new); } /** * Returns a function that determines whether a given stream is empty. * * @return A function that determines whether a given stream is empty. */ public static <A> F<Stream<A>, Boolean> isEmpty_() { return Stream::isEmpty; } /** * Returns a function that determines whether a given stream is not empty. * * @return A function that determines whether a given stream is not empty. */ public static <A> F<Stream<A>, Boolean> isNotEmpty_() { return Stream::isNotEmpty; } /** * Returns a stream of one element containing the given value. * * @param a The value for the head of the returned stream. * @return A stream of one element containing the given value. */ public static <A> Stream<A> single(final A a) { return cons(a, Stream::nil); } /** * Returns a function that yields a stream containing its argument. * * @return a function that yields a stream containing its argument. */ public static <A> F<A, Stream<A>> single() { return Stream::single; } /** * Prepends the given head element to the given tail element to produce a new stream. * * @param head The element to prepend. * @param tail The stream to prepend to. * @return The stream with the given element prepended. */ public static <A> Stream<A> cons(final A head, final F0<Stream<A>> tail) { return new Cons<>(head, tail); } /** * Joins the given stream of streams by concatenation. * * @param o The stream of streams to join. * @return A new stream that is the join of the given streams. */ public static <A> Stream<A> join(final Stream<Stream<A>> o) { return o.bind(identity()); } /** * A first-class version of join * * @return A function that joins a stream of streams using a bind operation. */ public static <A> F<Stream<Stream<A>>, Stream<A>> join() { return Stream::join; } /** * Unfolds across the given function starting at the given value to produce a stream. * * @param f The function to unfold across. * @param b The start value to begin the unfold. * @return A new stream that is a result of unfolding until the function does not produce a * value. */ public static <A, B> Stream<A> unfold(final F<B, Option<P2<A, B>>> f, final B b) { final Option<P2<A, B>> o = f.f(b); if (o.isNone()) return nil(); else { final P2<A, B> p = o.some(); return cons(p._1(), () -> unfold(f, p._2())); } } /** * Creates a stream where the first item is calculated by applying the function on the third argument, * the second item by applying the function on the previous result and so on. * * @param f The function to iterate with. * @param p The predicate which must be true for the next item in order to continue the iteration. * @param a The input to the first iteration. * @return A stream where the first item is calculated by applying the function on the third argument, * the second item by applying the function on the previous result and so on. */ public static <A> Stream<A> iterateWhile(final F<A, A> f, final F<A, Boolean> p, final A a) { return unfold( o -> Option.iif(p2 -> p.f(o), p(o, f.f(o))) , a); } /** * Takes the given iterable to a stream. * * @param i The iterable to take to a stream. * @return A stream from the given iterable. */ public static <A> Stream<A> iterableStream(final Iterable<A> i) { return iteratorStream(i.iterator()); } @SafeVarargs public static <A> Stream<A> arrayStream(final A...as) { return as.length == 0 ? Stream.nil() : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.none() : some(p(as[i], p(as, i + 1)))), p(as, 0)); } /** * Returns an infinite-length stream of the given element. * * @param a The element to repeat infinitely. * @return An infinite-length stream of the given element. */ public static <A> Stream<A> repeat(final A a) { return cons(a, () -> repeat(a)); } /** * Returns an infinite-length stream of the given elements cycling. Fails on the empty stream. * * @param as The elements to cycle infinitely. This must not be empty. * @return An infinite-length stream of the given elements cycling. */ public static <A> Stream<A> cycle(final Stream<A> as) { if (as.isEmpty()) throw error("cycle on empty list"); else return as.append(() -> cycle(as)); } /** * Returns a stream constructed by applying the given iteration function starting at the given value. * * @param f The iteration function. * @param a The value to begin iterating from. * @return A stream constructed by applying the given iteration function starting at the given value. */ public static <A> Stream<A> iterate(final F<A, A> f, final A a) { return cons(a, () -> iterate(f, f.f(a))); } /** * A first-class version of the iterate function. * * @return A function that returns a stream constructed by applying a given iteration function * starting at a given value. */ public static <A> F<F<A, A>, F<A, Stream<A>>> iterate() { return curry(Stream::iterate); } /** * A first-class version of the bind function. * * @return A function that binds a given function across a given stream, joining the resulting streams. */ public static <A, B> F<F<A, Stream<B>>, F<Stream<A>, Stream<B>>> bind_() { return curry((f, as) -> as.bind(f)); } /** * A first-class version of the foldRight function. * * @return A function that folds a given stream with a given function. */ public static <A, B> F<F<A, F<P1<B>, B>>, F<B, F<Stream<A>, B>>> foldRight() { return curry((f, b, as) -> as.foldRight(f, b)); } }