Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 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
Gavin Bisesi
@Daenyth
If it's something like an http4s client, you absolutely want one for the whole process lifetime
because the resource is expensive to construct, and what it gives you is more efficient per-usage actions
(it does connection pooling, keep-alive, etc)
most resources you want to construct once and then pass down to your app already-alive
it's relatively rare that you really want to be dealing with Resource inside your biz logic
Anand Krishnan
@iamanandkris
Yeah I am not happy the way I coded it, thanks for the suggestion @Daenyth and @djspiewak I will try to make it application level.
Matt
@mattgibb
Hello awesome cats-effect team! Thanks for all your hard work :)
Adam Rosien
@arosien
they are awesome!
Luis Rodero-Merino
@lrodero

Basically what I'm saying is it's hard to write tutorials :-)

Yes, absolutely :) . So, ok, agreed. @marcraminv and I will try to work on it. Thanks for the feedback!

rnd4222
@rnd4222_gitlab
Do you guys use explicit Kleisli in a "tagless-final" code, or hide it behind another parametric type, having (say) F and G for a types with and without context?
I'm aware of cats-mtl, but what if you need to eventually provide a context and convert reader-like G to a non-reader F?
Adam Rosien
@arosien

@rnd4222_gitlab like

trait Train[F[_]] {
  def toot(): F[Unit]
}

object Train {
  def apply: Train[Kleisli[IO, Whistle]] = ???
}

vs.

trait Train[F[_]] {
  def toot(): Kleisli[F, Whistle, Unit]
}

?

i usually use the former, and usually add

trait Train[F[_]] {
  def toot(): F[Unit]
  def mapK[G[_]](f: F ~> G): Train[G]
}

(cats-tagless can auto-generate these also)

rnd4222
@rnd4222_gitlab
@arosien more like
trait Train[F[_]]
trait Sound[F[_]]
class Whistle[F[_] : ApplicativeAsk[*[_], Volume], G[_]]
Adam Rosien
@arosien
does Whistle[F, G] extends Sound[F]?
sorry, i must be missing something
there's using Kleisli vs. ApplicativeAsk, that's one choice
rnd4222
@rnd4222_gitlab
I'm now working in a project where "tagless-final-to-the-max" approach was taken.
There is always different types for Fs with different contexts.
Lots of custom Lift/Unlift classes for conversion back and forth.
Oh, and it uses doobie, so add another two types - one is instantiated to ConnectionIO and second to Kleisli[ConnectionIO, ...], both with its own lifts-unlifts
So I wanted to know if its usual approach or not
Adam Rosien
@arosien
hmm. so for the impls/interpreters of those algebras there isn't 1 type like IO that's used for F, there are multiple, so you end up translating a lot?
is there some intermediate type like class BizLogic[F[_]](alg1: Alg1[F], alg2[Kleisli[F, Dependency]])? because something like that would be difficult.
or at least more complicated than it probably should be. but i'm just guessing because i'm not sure of the structure you are describing.
rnd4222
@rnd4222_gitlab
It's usually in a places where some context is added/eliminated, for example in HttpRoutes or SomethingRepository
typical signature is
def withRequestId[F[_], G[_] : WithRun[*[_], F, RequestId[F]](routes: HttpRoutes[F]): HttpRoutes[G]
Adam Rosien
@arosien
i definitely know that there are good reasons to need to lift/unlift between types, especially with Kleisli. but where that happens is the question.
rnd4222
@rnd4222_gitlab
I'm thinking that using Kleisli in this example would be much better:
def withRequestId[F[_], G[_] : WithRun[*[_], F, RequestId[F]](routes: HttpRoutes[F]): HttpRoutes[G]

// vs

def withRequestId[F[_]](routes: HttpRoutes[F]): HttpRoutes[Kleisli[F, RequestId[F], *]
Adam Rosien
@arosien
yeah that signature makes sense, sort of.
i see now what you're saying about monad transformers vs. typeclass constraints.

the former is more flexible, although it is likely that only Kleisli has a WithRun instance i'm guessing.

it's a familiarity issue, like you said. i think more folks would understand the Kleisli version since it is more "concrete"

Adam Rosien
@arosien
but i can see how some business logic is going to depend on [F[_]: WithRun[...]](routes: HttpRoutes[F]) which makes the context bound version more congruent
so... i feel ya.
Georgi Krastev
@joroKr21
It depends. With ApplicativeAsk it was easy to migrate from Kleisli to Monix TaskLocal. But it's better to have higher level interfaces like Logger. When converting to routes it sounds like a place to use concrete types though.
Adam Rosien
@arosien

there's the evalMap(f: A => F[B]): Resource[F, A] => Resource[F, B] = _.flatMap(a => Resource.liftF(f(a))) combinator that lifts the output of f into an "inner" Resource.

what about a different combinator that uses the first Resource to create the next, where the first can be released: evalUse(f: A => F[B]): Resource[F, A] => Resource[F, B] = rfa => Resource.liftF(rfa.use(f))?

or is there a better way?
Fabio Labella
@SystemFw
that's it
Keir Lawson
@keirlawson
Is there a nice pre-existing fake impl of Clock for use with tests? Obviously I can make my own but figured there might be something already?
Fabio Labella
@SystemFw
TestContext
Gavin Bisesi
@Daenyth
@keirlawson example integration with scalatest here https://gist.github.com/Daenyth/67575575b5c1acc1d6ea100aae05b3a9
Adam Rosien
@arosien
very quiet today in the gitterverse.
Michael Pilquist
@mpilquist
@arosien_twitter you’ve gotta hang out in cats-effect-dev channel
Adam Rosien
@arosien
:O
Fabio Labella
@SystemFw
yeah I think this channel is going to be for user questions (which I think is a good thing)
Aleksander Sumowski
@aleksandersumowski
hi all,
what would be a good way to extend IO.race to more then 2 tasks?
Fabio Labella
@SystemFw
@aleksandersumowski do they all return the same thing?
things of the same type I mean
Aleksander Sumowski
@aleksandersumowski
yes
This message was deleted
Fabio Labella
@SystemFw
@aleksandersumowski this should work
def multiRace[F[_]: Concurrent, A](fas: List[F[A]]): F[A] = {
  def spawn[B](fa: F[B]): Resource[F, Unit] =
    Resource.make(fa.start)(_.cancel).void

  def finish(fa: F[A], d: Deferred[F, Either[Throwable, A]]): F[Unit] =
    fa.attempt.flatMap(d.complete)

  Deferred[F, Either[Throwable, A]]
    .flatMap { result =>
      fas
        .traverse(fa => spawn(finish(fa, result)))
        .use(_ => result.get.rethrow)
    }
}

def program(i: Int) = {
  for {
    wait <- IO(scala.util.Random.nextInt(1000))
    _ <- IO(println(s"program $i waiting for $wait millis"))
    _ <- IO.sleep(wait.millis)
    _ <- IO(println(s"program $i finished"))
  } yield i
}.guarantee(IO(println(s"program $i finalised")))

def test = multiRace(List.range(0, 5).map(program)).unsafeRunSync
Aleksander Sumowski
@aleksandersumowski
thanks a lot!
Daniel Ochoa Rodríguez
@tzimisce012
About this PR: typelevel/cats-effect#365 Does it miss ConcurrentEffectfor IorT or am I missing something?