ValdemarGr / catch-effect

MTL, but without the MT
Apache License 2.0
9 stars 1 forks source link

Specialization for IO? #6

Closed jatcwang closed 18 hours ago

jatcwang commented 3 days ago

Are you open to contributions for API specialized for IO? I want to make this as simple as possible to adopt for those using IO and suffering for EitherT

ValdemarGr commented 3 days ago

That is a good idea. The docs (README) would also be more concise 🎉

ValdemarGr commented 3 days ago

What does your idea for a simpler API entail? Something like import catcheffect.io.* maybe?

jatcwang commented 3 days ago

I've put in a very barebone PR in #7. Let me know what you think!

Some other unrelated ideas from my own prototyping:

Instead of Raise I named it Abort, and instead of a Raise#raise method, I have Abort#apply, which allows the following API:

def doSomething()(implicit abort: Abort[DomainError]): IO[String] = {
  for {
    _ <- ...
    _ <-  abort(DomainError.Err1(..))
  } yield ...
}

I think raise(DomainError.Err1(..)) will work well too but abort definitely catches my attention more :smile:

ValdemarGr commented 3 days ago

It looks nice to not have to wire a Catch instance through the whole application :+1:

The naming and structure of the current algebra stems from cats-mtl.

Have you also handled naming for the IO-specialized instance of Handle in your prototype?

I don't think I have seen apply on an algebra before, I think Abort[F]("error") looks a bit funny, but maybe I have been trained to always expect a method after typeclass summoning :smiley:.

The only case of a specialized (and IO in fact) MTL typeclass is IOLocal, they also have another naming scheme for IO specialized datatypes here (a bit funny that one starts with IO[Local] and others end with [Outcome]IO).

Maybe we could add something akin to MTL extension methods?

// not entirely sure this works nice with type inference
extension [A](a: A)
  def abort[F[_], E >: A, C](using raise: Raise[IO, E]): IO[C] = raise.raise(a: E)

def doSomething()(implicit raise: Raise[IO, DomainError]): IO[String] = {
  for {
    _ <- ...
    _ <-  DomainError.Err1(..).abort
  } yield ...
}

This needs more work since there are 3 type parameters which I get the feeling will cause inference problems. This is how cats-mtl does it.

jatcwang commented 2 days ago

No I didn't have a equivalent for Handle. Was just a clean room minimal prototype and I needed an alternative name for Raise :smile:

As for the extension methods, I think for readability I prefer "operation first", so R.raise(..) is fine to me.

If you're happy with the IO API I'll continue to polish it :+1: Thanks!

ValdemarGr commented 2 days ago

I think the current implementation looks good 👍.