diff --git a/cyclops-vavr/src/main/java/cyclops/companion/vavr/Streams.java b/cyclops-vavr/src/main/java/cyclops/companion/vavr/Streams.java index 43e86f57..edc3dcf1 100644 --- a/cyclops-vavr/src/main/java/cyclops/companion/vavr/Streams.java +++ b/cyclops-vavr/src/main/java/cyclops/companion/vavr/Streams.java @@ -1,5 +1,6 @@ package cyclops.companion.vavr; +import cyclops.control.*; import cyclops.monads.VavrWitness.queue; import cyclops.monads.VavrWitness.tryType; import io.vavr.Lazy; @@ -9,10 +10,6 @@ import com.aol.cyclops.vavr.hkt.*; import cyclops.companion.CompletableFutures; import cyclops.companion.Optionals; -import cyclops.control.Eval; -import cyclops.control.Maybe; -import cyclops.control.Reader; -import cyclops.control.Xor; import cyclops.conversion.vavr.FromCyclopsReact; import cyclops.monads.*; import cyclops.monads.VavrWitness.*; @@ -39,6 +36,7 @@ import cyclops.typeclasses.monad.*; import io.vavr.collection.List; import io.vavr.collection.Stream; +import io.vavr.control.Try; import lombok.experimental.UtilityClass; import org.jooq.lambda.tuple.Tuple2; @@ -72,13 +70,20 @@ public static Stream tailRec(T initial, Function e.fold(s -> { - newValue[0]=true; - return fn.apply(s); }, - p -> { - newValue[0]=false; - return Stream.of(e); - })); + Stream> rebuild = Stream.of(); + for(Either e : next){ + Stream> r = e.fold(s -> { + newValue[0] = true; + + return fn.apply(s); + }, + p -> { + newValue[0] = false; + return Stream.of(e); + }); + rebuild = Stream.concat(rebuild,r); + } + next = rebuild; if(!newValue[0]) break; @@ -92,13 +97,21 @@ public static Stream tailRecXor(T initial, Function e.visit(s -> { - newValue[0]=true; - return fn.apply(s); }, - p -> { - newValue[0]=false; - return Stream.of(e); - })); + Stream> rebuild = Stream.of(); + for(Xor e : next){ + Stream> r = e.visit(s -> { + newValue[0] = true; + + return fn.apply(s); + }, + p -> { + newValue[0] = false; + return Stream.of(e); + }); + rebuild = Stream.concat(rebuild,r); + } + + next = rebuild; if(!newValue[0]) break; @@ -114,18 +127,20 @@ public static R foldRightUnsafe(Stream stream,R identity, BiFunction R foldRight(Stream stream,R identity, BiFunction fn){ - return foldRightRec(stream,Eval.now(identity),(a,b)-> b.map(b2->fn.apply(a,b2))).get(); - } - private static Eval foldRightRec(Stream stream,Eval identity, BiFunction, ? extends Eval> fn){ + public static R foldRight(Stream stream,R identity, BiFunction p){ + class Step{ + public Trampoline loop(Stream s, Function> fn){ + if (s.isEmpty()) + return fn.apply(identity); + return Trampoline.more(()->loop(s.tail(), rem -> Trampoline.more(() -> fn.apply(p.apply(s.head(), rem))))); - if(stream.isEmpty()) - return identity; - else - return identity.flatMap(i-> fn.apply(stream.head(), foldRightRec(stream.tail(), identity, fn))); + } + } + return new Step().loop(stream,i->Trampoline.done(i)).result(); } + public static AnyMSeq anyM(Stream option) { return AnyM.ofSeq(option, stream.INSTANCE); } diff --git a/cyclops-vavr/src/test/java/cyclops/MonadRecTest.java b/cyclops-vavr/src/test/java/cyclops/MonadRecTest.java new file mode 100644 index 00000000..78f7cd34 --- /dev/null +++ b/cyclops-vavr/src/test/java/cyclops/MonadRecTest.java @@ -0,0 +1,39 @@ +package cyclops; + +import com.aol.cyclops.vavr.hkt.ListKind; +import com.aol.cyclops2.hkt.Higher; +import cyclops.async.Future; + +import cyclops.companion.vavr.Lists; +import cyclops.companion.vavr.Streams; +import cyclops.control.Xor; +import cyclops.monads.VavrWitness; +import cyclops.monads.VavrWitness.list; +import cyclops.monads.VavrWitness.stream; +import cyclops.stream.ReactiveSeq; +import cyclops.typeclasses.monad.MonadRec; +import io.vavr.collection.List; +import io.vavr.collection.Stream; +import org.junit.Test; + +import java.util.Optional; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + + +public class MonadRecTest { + + @Test + public void listTest(){ + MonadRec mr = Lists.Instances.monadRec(); + List l = Lists.tailRecXor(0, i -> i < 100_000 ? List.of(Xor.secondary(i + 1)) : List.of(Xor.primary(i + 1))); + assertThat(l,equalTo(List.of(100_001))); + } + @Test + public void streamTest(){ + MonadRec mr = Streams.Instances.monadRec(); + Stream l = Streams.tailRecXor(0, i -> i < 100_000 ? Stream.of(Xor.secondary(i + 1)) : Stream.of(Xor.primary(i + 1))); + assertThat(l,equalTo(Stream.of(100_001))); + } +} diff --git a/cyclops-vavr/src/test/java/cyclops/StreamsTest.java b/cyclops-vavr/src/test/java/cyclops/StreamsTest.java new file mode 100644 index 00000000..07f14c1e --- /dev/null +++ b/cyclops-vavr/src/test/java/cyclops/StreamsTest.java @@ -0,0 +1,24 @@ +package cyclops; + +import cyclops.companion.vavr.Streams; +import io.vavr.collection.Stream; +import org.junit.Test; + + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by johnmcclean on 08/08/2017. + */ +public class StreamsTest { + + @Test + public void simpleFoldRight(){ + assertThat(Streams.foldRight(Stream.of(1,2,3),0,(a,b)->a+b),equalTo(6)); + } + @Test + public void stackBuster(){ + assertThat(Streams.foldRight(Stream.range(0,100_000),0,(a,b)->a+b),equalTo(704982704)); + } +}