@cosmir17,
placeStone operation seems complicated(multiple fold and etc) and will take a long time (around 300ms?).
Sync.delay
is intended to capture side effects. In your original example mutating grid
would, indeed, be a side effect. However a CPU-intensive expression is generally not considered a side effect, so you don't have to delay
it. If you want to have a tight control over when it gets evaluated, you should look at Eval
in Cats instead.
I am doing it as a practice for Cats effect
In my experience, while tagless final approach (parameterizing with F[_]
) seems neat, it tends to also introduce unnecessary complexity. Personally, I try to go with concrete types (Either
, IO
etc.) first, unless I know I will have to mix domains that require different monad capabilities.
My MapRef implementation does.
@ChristopherDavenport Thank you, I shall read your test class.
flatMap
effects to make them "happen".flatMap
? Why can't I, say,. map over an fs2.Stream
of effects and have them "executed"? Is the choice of flatMap
arbitrary or are there mathematical laws at play here? If so, what are these laws?
F[A]
map: F[A] => (A => B) => F[B]
cannot execute further effects in the function simply because there are none there
A => F[B]
,which on more fundamental level, it's the general concept of a continuation when you represents effects in this style (programs as values)
Stream
you have evalMap: Stream[F, A] => (A => F[B) => Stream[F, B]
flatMap(a => Stream.eval(f(a))
flatMap
in strict side-effecting languages as well, if you squint
flatMap
@SystemFw I guess as a newbie I don't have the mental model. I've learned by rote that one must flatMap
but I can see why after years of mapping over Scala collections one might naively think this:
val printEffect: Int => IO[Unit] = x => IO { println(x) }
val printEach: Pipe[IO, Int, Unit] = { _.map(x => printEffect(x)) }
printEach(Stream(1, 2, 3, 4, 5)).compile.toList
prints out the numbers 1 to 5.
It is, of course, wrong. But why (other than "it just is") is currenlty eluding me.
Can you please expand on why A => F[B]
is a program and F[A] => (A => B) => F[B]
is not?
B
println
doesn't exist, as you note
println: Unit
purePrintLn: IO[Unit]
map: F[A] => (A => B) => F[B]
F
is Stream
map: Stream[IO, A] => (A => B) => Stream[IO, B]
A
is Int
A => B
unifies with Int => IO[Unit]
Pipe[IO, Int, IO[Unit]]