
com.github.tonivade.purefun.stream.Cons Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2020, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun.stream;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Function2;
import com.github.tonivade.purefun.Higher1;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.Matcher1;
import com.github.tonivade.purefun.PartialFunction1;
import com.github.tonivade.purefun.Producer;
import com.github.tonivade.purefun.Tuple;
import com.github.tonivade.purefun.Tuple2;
import com.github.tonivade.purefun.type.Option;
import com.github.tonivade.purefun.typeclasses.MonadDefer;
import static java.util.Objects.requireNonNull;
final class Cons implements Stream {
private final MonadDefer monad;
private final Higher1 head;
private final Stream tail;
Cons(MonadDefer monad, Higher1 head, Stream tail) {
this.monad = requireNonNull(monad);
this.head = requireNonNull(head);
this.tail = requireNonNull(tail);
}
@Override
public Higher1> headOption() {
return monad.map(head, Option::some);
}
@Override
public Higher1, Stream>>> split() {
return monad.pure(Option.some(Tuple.of(head, tail)));
}
@Override
public Stream concat(Stream other) {
return suspend(() -> cons(head, tail.concat(other)));
}
@Override
public Stream append(Higher1 other) {
return suspend(() -> cons(head, tail.append(other)));
}
@Override
public Stream prepend(Higher1 other) {
return suspend(() -> cons(other, tail.prepend(head)));
}
@Override
public Stream take(int n) {
return n > 0 ? suspend(() -> cons(head, tail.take(n - 1))) : empty();
}
@Override
public Stream drop(int n) {
return n > 0 ? suspend(() -> tail.drop(n - 1)) : this;
}
@Override
public Stream takeWhile(Matcher1 matcher) {
return suspendF(() -> monad.map(head,
t -> matcher.match(t) ? cons(head, tail.takeWhile(matcher)) : empty()));
}
@Override
public Stream dropWhile(Matcher1 matcher) {
return suspendF(() ->
monad.map(head, t -> matcher.match(t) ?
tail.dropWhile(matcher) : this));
}
@Override
public Stream filter(Matcher1 matcher) {
return suspendF(() ->
monad.map(head, t -> matcher.match(t) ?
cons(head, tail.filter(matcher)) : tail.filter(matcher)));
}
@Override
public Stream collect(PartialFunction1 partial) {
return suspendF(() ->
monad.map(head, t -> partial.isDefinedAt(t) ?
cons(monad.map(head, partial::apply), tail.collect(partial)) : tail.collect(partial)));
}
@Override
public Higher1 foldLeft(R begin, Function2 combinator) {
return monad.flatMap(head, h -> tail.foldLeft(combinator.apply(begin, h), combinator));
}
@Override
public Higher1 foldRight(Higher1 begin, Function2, Higher1> combinator) {
return monad.flatMap(head, h -> tail.foldRight(combinator.apply(h, begin), combinator));
}
@Override
public Higher1 exists(Matcher1 matcher) {
return foldRight(monad.pure(false), (t, acc) -> matcher.match(t) ? monad.pure(true) : acc);
}
@Override
public Higher1 forall(Matcher1 matcher) {
return foldRight(monad.pure(true), (t, acc) -> matcher.match(t) ? acc : monad.pure(false));
}
@Override
public Stream map(Function1 map) {
return suspend(() -> cons(monad.map(head, map), suspend(() -> tail.map(map))));
}
@Override
public Stream mapEval(Function1> mapper) {
return suspend(() -> cons(monad.flatMap(head, mapper), suspend(() -> tail.mapEval(mapper))));
}
@Override
public Stream flatMap(Function1> map) {
return suspendF(() ->
monad.map(
monad.map(head, map),
s -> s.concat(tail.flatMap(map))));
}
@Override
public Stream repeat() {
return concat(suspend(this::repeat));
}
@Override
public Stream intersperse(Higher1 value) {
return suspend(() -> cons(head, suspend(() -> cons(value, tail.intersperse(value)))));
}
@Override
public StreamModule getModule() { throw new UnsupportedOperationException(); }
private Stream cons(Higher1 head, Stream tail) {
return new Cons<>(monad, head, tail);
}
private Stream suspend(Producer> stream) {
return suspendF(stream.map(monad::>pure));
}
private Stream suspendF(Producer>> stream) {
return new Suspend<>(monad, monad.defer(stream));
}
private Stream empty() {
return new Nil<>(monad);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy