You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unfortunately this map operation is not equivalent with a flatMap(f.andThen(pure)) because by not suspending execution it can trigger stack overflow errors.
As use-case, here's a toy Iterant implementation:
importcats.effect.IOsealedtraitIterant[+A] {
overridedeftoString="Iterant"
}
caseclassNext[+A](head: A, rest: IO[Iterant[A]]) extendsIterant[A]
caseclassSuspend[+A](rest: IO[Iterant[A]]) extendsIterant[A]
caseclassHalt(ex: Option[Throwable]) extendsIterant[Nothing]
// And a filter operationdeffilter[A](f: A=>Boolean)(stream: Iterant[A]):Iterant[A] =
stream match {
caseNext(a, rest) =>valtail= rest.map(filter(f))
if (f(a)) Next(a, tail) elseSuspend(tail)
caseSuspend(rest) =>Suspend(rest.map(filter(f)))
caseHalt(_) =>
stream
}
The filter is pretty straightforward. Now lets build an already evaluated stream and filter it:
valstream= (0 until 1000000).foldLeft(Halt(None) :Iterant[Int]) {
(acc, elem) =>Next(elem, IO.pure(acc))
}
filter((x: Int) => x %2==0)(stream)
//=> StackOverflowException
Currently this filter operation blows with a StackOverflowException.
Why this is bad
Having users to remember which operations are safe and which operations can blow up in their face and in what contexts makes for a really bad user experience. io.map(f) should be equivalent with io.flatMap(x => pure(f(x))) in all contexts, safety comes before performance.
Also monix.tail.Iterant is a real example shipping in Monix 3.0 which is generic over F[_] data types, making use of cats.effect.Sync.
So I'd like a test for this to be in SyncLaws.
The text was updated successfully, but these errors were encountered:
Currently
map
is defined like this:Unfortunately this
map
operation is not equivalent with aflatMap(f.andThen(pure))
because by not suspending execution it can trigger stack overflow errors.As use-case, here's a toy
Iterant
implementation:The
filter
is pretty straightforward. Now lets build an already evaluated stream and filter it:Currently this
filter
operation blows with aStackOverflowException
.Why this is bad
Having users to remember which operations are safe and which operations can blow up in their face and in what contexts makes for a really bad user experience.
io.map(f)
should be equivalent withio.flatMap(x => pure(f(x)))
in all contexts, safety comes before performance.Also
monix.tail.Iterant
is a real example shipping in Monix 3.0 which is generic overF[_]
data types, making use ofcats.effect.Sync
.So I'd like a test for this to be in
SyncLaws
.The text was updated successfully, but these errors were encountered: