Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Raise#fromEither and friends #514

Merged
merged 3 commits into from
Feb 2, 2024

Conversation

armanbilge
Copy link
Member

@armanbilge armanbilge commented Aug 3, 2023

Inspired by discussion with @benhutchison in typelevel/cats-effect#3765 (reply in thread). The idea is to add a bunch of methods for lifting from the "primitive" monads Either, Reader, Writer, State into F[_]. This complements #489 which pushes towards using IO for F[_] instead of the monad transformers EitherT, Kleisli, WriterT, and StateT. So we need a mechanism for lifting.

  • Ask#fromReader
  • Raise#fromEither (analogous to ApplicativeError#fromEither)
  • Stateful#fromState
  • Tell#fromWriter

Comment on lines +57 to +58
def fromKleisli[A](ka: Kleisli[F, E, A])(implicit F: FlatMap[F]): F[A] =
ask.flatMap(ka.run(_))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andrew raised a great question about use-cases, which made me realize we can do even better 🙂

For example suppose you have a Ask[IO, Request[IO]] and you want to interop with an http4s thing Kleisli[IO, Request[IO], Response[IO]]. Well, now you can!

@benhutchison
Copy link
Member

As one user of this library, I'd like to "bias towards action" and see you merge this @armanbilge, and some version of the error submarine if you see fit.

I think currently the risks of stagnation exceed the risks from lightly reviewed code getting merged, so my preference is for low barriers to contribution, for non-breaking changes at least.

@armanbilge
Copy link
Member Author

As one user of this library, I'd like to "bias towards action" and see you merge this @armanbilge

@benhutchison I literally cannot merge my own PRs :) I can however review and merge work submitted by others.

Co-authored-by: Igor Ramazanov <igor.ramazanov@protonmail.com>

def fromOptionT[E2 <: E, A](ota: OptionT[F, A])(e: => E2)(implicit F: Monad[F]): F[A] =
F.flatMap(ota.value)(oa => fromOption(oa)(e))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def fromValidated[E2 <: E, A](va: Validated[E2, A])(implicit F: Applicative[F]): F[A] =
va.fold(raise, F.pure)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we are not accidentally adding a performance penalty comparing with, for example:

  def fromValidated[E2 <: E, A](va: Validated[E2, A])(implicit F: Applicative[F]): F[A] =
    va match {
      case Validated.Invalid(e) => raise(e)
      case Validated.Valid(a) => F.pure(a)
    }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we are. Using fold requires allocating lambdas, pattern matching does not. I don't think it's important in practice.

Copy link
Member

@djspiewak djspiewak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bike-shedding a bit, the from prefix threw me for quite a while as I was trying to parse this. I can't think of a better name though. This is absolutely a nice addition.

@djspiewak djspiewak merged commit 226f0b8 into typelevel:main Feb 2, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants