
com.github.tonivade.purefun.stream.PureStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of purefun-stream Show documentation
Show all versions of purefun-stream Show documentation
Functional Programming Library for Java
The newest version!
/*
* Copyright (c) 2018-2024, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun.stream;
import static com.github.tonivade.purefun.core.Unit.unit;
import static com.github.tonivade.purefun.data.Sequence.asStream;
import java.util.Arrays;
import java.util.stream.Stream;
import com.github.tonivade.purefun.HigherKind;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.core.Bindable;
import com.github.tonivade.purefun.core.Function1;
import com.github.tonivade.purefun.core.Function2;
import com.github.tonivade.purefun.core.Matcher1;
import com.github.tonivade.purefun.core.Operator1;
import com.github.tonivade.purefun.core.PartialFunction1;
import com.github.tonivade.purefun.core.Producer;
import com.github.tonivade.purefun.core.Tuple;
import com.github.tonivade.purefun.core.Tuple2;
import com.github.tonivade.purefun.core.Unit;
import com.github.tonivade.purefun.data.ImmutableList;
import com.github.tonivade.purefun.data.Sequence;
import com.github.tonivade.purefun.type.Option;
import com.github.tonivade.purefun.typeclasses.Instances;
import com.github.tonivade.purefun.typeclasses.MonadDefer;
@HigherKind
public sealed interface PureStream, T>
extends PureStreamOf, Bindable, T>
permits Cons, Suspend, Nil {
default PureStream head() {
return take(1);
}
default PureStream tail() {
return drop(1);
}
Kind> headOption();
Kind, PureStream>>> split();
PureStream concat(PureStream other);
PureStream append(Kind other);
PureStream prepend(Kind other);
PureStream take(int n);
PureStream drop(int n);
PureStream filter(Matcher1 super T> matcher);
PureStream takeWhile(Matcher1 super T> matcher);
PureStream dropWhile(Matcher1 super T> matcher);
default PureStream filterNot(Matcher1 super T> matcher) {
return filter(matcher.negate());
}
PureStream collect(PartialFunction1 super T, ? extends R> partial);
Kind foldLeft(R begin, Function2 super R, ? super T, ? extends R> combinator);
Kind foldRight(Kind begin,
Function2 super T, ? super Kind, ? extends Kind> combinator);
@Override
PureStream map(Function1 super T, ? extends R> map);
@Override
PureStream flatMap(Function1 super T, ? extends Kind, ? extends R>> map);
@Override
default PureStream andThen(Kind, ? extends R> next) {
return flatMap(ignore -> next);
}
PureStream mapEval(Function1 super T, ? extends Kind> mapper);
PureStream repeat();
PureStream intersperse(Kind value);
Kind exists(Matcher1 super T> matcher);
Kind forall(Matcher1 super T> matcher);
default , R> PureStream through(Function1, PureStream> function) {
return function.apply(this);
}
default Kind> asSequence() {
return foldLeft(ImmutableList.empty(), Sequence::append);
}
default Kind asString() {
return foldLeft("", (acc, a) -> acc + a);
}
default Kind drain() {
return foldLeft(unit(), (acc, a) -> acc);
}
default PureStream mapReplace(Kind next) {
return mapEval(ignore -> next);
}
static > PureStream.Of of(MonadDefer monad) {
return () -> monad;
}
static > PureStream.Of of(Class type) {
return of(Instances.monadDefer(type));
}
@SafeVarargs
static > PureStream.Of of(F...reified) {
return of(Instances.monadDefer(reified));
}
@SafeVarargs
static , T> PureStream empty(F... reified) {
return of(Instances.monadDefer(reified)).empty();
}
@SafeVarargs
static , T> PureStream pure(T value, F...reified) {
return of(Instances.monadDefer(reified)).pure(value);
}
@SafeVarargs
static , T> PureStream cons(T head, PureStream tail, F...reified) {
return of(Instances.monadDefer(reified)).cons(head, tail);
}
@SafeVarargs
static , T> PureStream suspend(Producer extends PureStream> lazy, F...reified) {
return of(Instances.monadDefer(reified)).suspend(lazy);
}
@SafeVarargs
static , T> PureStream eval(Kind value, F...reified) {
return of(Instances.monadDefer(reified)).eval(value);
}
@SafeVarargs
static , T> PureStream from(Iterable extends T> iterable, F...reified) {
return of(Instances.monadDefer(reified)).from(iterable);
}
@SafeVarargs
static , T> PureStream from(Stream extends T> stream, F...reified) {
return of(Instances.monadDefer(reified)).from(stream);
}
@SafeVarargs
static , T> PureStream from(Sequence extends T> sequence, F...reified) {
return of(Instances.monadDefer(reified)).from(sequence);
}
@SafeVarargs
static , T, S> PureStream unfold(
S seed, Function1 super S, Option>> function, F...reified) {
return of(Instances.monadDefer(reified)).unfold(seed, function);
}
@SafeVarargs
static , T> PureStream iterate(T seed, Operator1 generator, F...reified) {
return of(Instances.monadDefer(reified)).iterate(seed, generator);
}
@SafeVarargs
static , T> PureStream iterate(Producer extends T> generator, F...reified) {
return of(Instances.monadDefer(reified)).iterate(generator);
}
@SafeVarargs
static , A, B, R> PureStream zipWith(PureStream s1, PureStream s2,
Function2 super A, ? super B, ? extends R> combinator, F...reified) {
return of(Instances.monadDefer(reified)).zipWith(s1, s2, combinator);
}
@SafeVarargs
static , A, B> PureStream> zip(PureStream s1, PureStream s2, F...reified) {
return of(Instances.monadDefer(reified)).zip(s1, s2);
}
@SafeVarargs
static , A> PureStream> zipWithIndex(PureStream stream, F...reified) {
return of(Instances.monadDefer(reified)).zipWithIndex(stream);
}
@SafeVarargs
static , A> PureStream merge(PureStream s1, PureStream s2, F...reified) {
return of(Instances.monadDefer(reified)).merge(s1, s2);
}
interface Of> {
MonadDefer monadDefer();
default PureStream empty() {
return new Nil<>(monadDefer());
}
@SuppressWarnings("unchecked")
default PureStream of(T... values) {
return from(Arrays.stream(values));
}
default PureStream pure(T value) {
return eval(monadDefer().pure(value));
}
default PureStream cons(T head, PureStream tail) {
return pure(head).concat(tail);
}
default PureStream suspend(Producer extends PureStream> lazy) {
return new Suspend<>(monadDefer(),
monadDefer().defer(
lazy.andThen(PureStreamOf::toPureStream).map(monadDefer()::>pure)));
}
default PureStream eval(Kind value) {
return new Cons<>(monadDefer(), Kind.narrowK(value), empty());
}
default PureStream from(Iterable extends T> iterable) {
return from(asStream(iterable.iterator()));
}
default PureStream from(java.util.stream.Stream extends T> stream) {
return from(ImmutableList.from(stream));
}
default PureStream from(Sequence extends T> sequence) {
return sequence.foldLeft(empty(), (acc, a) -> acc.append(monadDefer().pure(a)));
}
default PureStream unfold(S seed, Function1 super S, Option>> function) {
return suspend(() -> doUnfold(seed, function));
}
default PureStream iterate(T seed, Operator1 generator) {
return cons(seed, suspend(() -> iterate(generator.apply(seed), generator)));
}
default PureStream iterate(Producer extends T> generator) {
return unfold(unit(), unit -> Option.of(generator).map(next -> Tuple.of(next, unit)));
}
default PureStream zipWith(PureStream s1, PureStream s2,
Function2 super A, ? super B, ? extends R> combinator) {
return new Suspend<>(monadDefer(), monadDefer().defer(
() -> monadDefer().mapN(s1.split(), s2.split()).apply(
(op1, op2) -> {
Option> result = Option.map2(op1, op2,
(t1, t2) -> {
Kind head = monadDefer().mapN(t1.get1(), t2.get1()).apply(combinator);
PureStream tail = zipWith(t1.get2(), t2.get2(), combinator);
return new Cons<>(monadDefer(), head, tail);
});
return result.getOrElse(this::empty);
})
));
}
default PureStream> zip(PureStream s1, PureStream s2) {
return zipWith(s1, s2, Tuple2::of);
}
default PureStream> zipWithIndex(PureStream stream) {
return zip(stream, iterate(0, x -> x + 1));
}
// TODO: generics
default PureStream merge(PureStream s1, PureStream s2) {
return new Suspend<>(monadDefer(), monadDefer().defer(
() -> monadDefer().mapN(s1.split(), s2.split()).apply(
(opt1, opt2) -> {
Option> result = Option.map2(opt1, opt2,
(t1, t2) -> {
Kind head = t1.get1();
PureStream tail = eval(t2.get1()).concat(merge(t1.get2(), t2.get2()));
return new Cons<>(monadDefer(), head, tail);
});
return result.getOrElse(this::empty);
})
));
}
private PureStream doUnfold(S seed, Function1 super S, Option>> function) {
return function.apply(seed)
.map(tuple -> tuple.applyTo((t, s) -> cons(t, suspend(() -> doUnfold(s, function)))))
.getOrElse(this::empty);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy