Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • Sep 05 2019 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 2019 21:17
    codecov-io commented #484
  • Jan 31 2019 21:08
    scala-steward opened #484
  • Jan 31 2019 18:19
    andywhite37 commented #189
  • Jan 31 2019 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 2019 00:01
    codecov-io commented #483
  • Jan 29 2019 23:51
    deniszjukow opened #483
  • Jan 29 2019 23:37
  • Jan 29 2019 23:22
  • Jan 29 2019 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 2019 18:01
    jdegoes commented #480
  • Jan 29 2019 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 2019 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 2019 07:12
    alexandru commented #480
  • Jan 28 2019 05:45
    codecov-io commented #482
  • Jan 28 2019 05:35
    daron666 opened #482
  • Jan 27 2019 13:56
    codecov-io commented #481
  • Jan 27 2019 13:46
    lrodero opened #481
  • Jan 27 2019 05:47
    codecov-io commented #460
  • Jan 27 2019 05:37
    codecov-io commented #460
Rohde Fischer
@capacman I'm fairly new to effects, but to me it looks correct. I'm wondering though if you'd need a begin transaction call. I seem to recall the ExitCase of bracket is a sealed trait, so I think you'll get a compiler warning if you don't cover all cases possible, but if I remember wrong then you might consider a default case where you do a rollback. Also slightly beside your point, I'll strongly urge you to log errors, including the input that cause them ;)
anil chalil
Hi @rfftrifork , thank you for comments. Yes some logging absolutely necessary. I just wonder what happens in case of a exception in bracketcase? Because in documentation it say behavior depends on impl of F. Probably i need to write a test. Thanks again
Rohde Fischer
@capacman I think it will work, but I agree, a test is a very good idea, especially because then you have a chance of finding out if the behavior breaks
Rohde Fischer

hmm does anyone have some advice/experience/best practices with how to write better tests with effects? Currently I'm doing mixing of for comprehensions and unsafeRunSync, but it feels kind of awkward, I just cannot see how else to do it, e.g.:

"My app" should "do bar" in {
val barsF = for {
    foo <- foo()
    bars <- foo.bars()
} yield bars

val bars = barsF.unsafeRunSync

// tests go here

I'm struggling a bit, because in a way the cleanest would be to do the tests as F[_]s too, such that they are just a part of the for comprehension, but in a way it also feels slightly off/awkward to me

Georgi Krastev
If you're using scalatest, it supports tests returning futures as well. Check the Async* styles. I guess it's not too difficult to add utilities for IO or for any F[_]: Effect. There is a lot of chatter about pure FP testing frameworks recently but idk if there is anything ready to be used.
Rohde Fischer
@joroKr21 thanks, will look into that, I am indeed using scalatest
Daniel Spiewak

Opinion time! What should the following be?

F.racePair(F.raiseError(e), fb)

The choices here:

  1. F.raiseError(e)
  2. fb.map(b => Right((F.raiseError(e).start, b)))
I'm leaning towards the latter since it gives more power, particularly when you consider how it interacts with race, but it's actually unspecified right now
I would guess that everyone just picks 2 without realizing it
also @rfftrifork you may be interested in this: https://github.com/djspiewak/cats-effect-testing
Rohde Fischer
@djspiewak thanks a lot, will take a look once I'm over my current hurdle :)
Fabio Labella
@djspiewak do you mean do start fb as well in no 2?
Daniel Spiewak
@SystemFw yeah I do. I missed a flatMap there; adjusting
F.raiseError(e).start.flatMap(f => fb.map(b => Right((f, b))))
Fabio Labella
well, my expectation is that both sides in a race are started, for fairness
Daniel Spiewak
right, they would be
I'm just clarifying the outcome
Fabio Labella
ah, ok, sorry
Daniel Spiewak
Fabio Labella
anyway yes, you wouldn't want raiseError to always win by default like in 1
or at least I wouldn't :P
Daniel Spiewak
it'd be weird
but I noticed it wasn't actually codified by laws
Julien Truffaut
Hi all, do you know where could I find a sketch of IO implementation including Async? It doesn't have to be stack safe or efficient, it is more to understand how the run loop works
Gavin Bisesi
I'd peek at pre-0.10 versions of cats-effect
Fabio Labella
@Daenyth the runloop works differently now though
one of the ideas for when the days have 36 hours is a series of blog posts about a real world (so concurrency, interruption and so ) version of IO that prioritises code clarity over performance for ease of understanding
@julien-truffaut not as nice as having a code sketch, but do feel free to ask questions instead
Gavin Bisesi
Fabio Labella
the advice of looking at the old cats-effect is still valid though, and I am giving a talk on fibers which should bring more light on the internals (and Async is in many ways the key for everything)
Luka Jacobowitz
Man I can’t wait for days to have 36 hours
I’m gonna get so much done
Just need to figure out how to slow earth’s rotation somehow
Daniel Spiewak
@julien-truffaut so conceptually, you can get an idea for the model by implementing something like type Task[A] = EitherT[ContT[Free[() => ?, ?], Unit, ?], Throwable, A],
more abstractly, IO is two free monads glued together with an interpreter that can sequence back and forth between them. Cont is itself a free monad for a coalgebra, while Free is obviously… uh, Free, and we instantiate it with a trivial algebra
the run loop today behaves radically different than this though
the naive run loop structure for the above type works, but is very slow and also sometimes quite tricky to get right (e.g. stack safety for raiseError is hard with the above)
the more Enterprise Grade runloop structure requires a lot more groundwork :-)
I'm not sure exactly what you're looking for
Fabio Labella
I find the actual runloop to be easier to understand than the type above :smile:
Daniel Spiewak
I think the above is only confusing because Cont is so bizarre
and ContT is even more bizarre
Fabio Labella
yeah if you unroll it it makes sense
Daniel Spiewak
I have an old, old, old gist that I put together with Brian McKenna where we reimplemented scalaz.Task in terms of scalaz's ContT and scalaz.effect.IO, for maximum yoloswag
it had an exceptionally cool bit where we defined Task.liftIO
and it was literally just flatMap on ContT
which I thought was clever
Fabio Labella

I would start looking at the runloop from these 3 points:

  • IO it's a tree that gets translated, and each node in the tree represent a fundamental concept (so you have Async, Delay, Attempt, Pure, FlatMap)
  • The runloop keeps a state, which is roughly case class State(current: IO[Any], stack: List[Any => IO[Any]]. Each iteration pattern matches on current, does some stuff, and keeps going by taking the next off the stack.
  • The (slightly simplified) type of Async is case class Async(f: (Either[Throwable, A] => Unit) => Unit) extends IO[A]. The key point is that Async does not introduce any asynchrony, it just wraps something that can already do asynchrony by itself. It's kinda funny in that Asyncdoes most of the work for the "complex" stuff, but actually the only thing it does is passing a function to another function.

I can expand and unpack some of this if needed