Cats: `TryT` Monad transformer for `Try`

Created on 5 Jul 2019  Â·  3Comments  Â·  Source: typelevel/cats

There is an EitherT, making it possible to rotate effects which can throw into F[_] by using EitherT[F[_], Throwable, A]. I think it'd be great if a similar thing existed for Try. Currently, this is possible by converting the Try[A] into Either[Throwable, A] with try.toEither. We could support Try by doing something like (thanks @LukaJCB for this code in the cats-mtl gitter):

type TryT[F[_], A] = EitherT[F, Throwable, A]

object TryT {
  def apply[F[_]: Functor, A](value: F[Try[A]]): TryT[F, A] = EitherT(value.map(_.toEither))
  def liftF[F[_]: Functor, A](fa: F[A]): TryT[F, A] = EitherT(fa.map(Right(_)))
  def fromTry[F[_]: Applicative, A](v: Try[A]): TryT[F, A] = apply(Applicative[F].pure(v))
}

Most helpful comment

Just to play devil's advocate here… What would the semantics of this be? Try catches in map/flatMap, would TryT as well? Try really isn't that different from Either[Throwable, ?], except that it pretends to be a Sync in some ways by catching exceptions, so isn't it correct that the only way to use it in higher level abstractions is to go through Either?

I understand that Try is used a lot, but I'd be really leery of trying to do something like a monad transformer for a monad that isn't really a monad (it violates the functor laws if you throw, which is the whole point of using Try in the first place, so it most definitely violates the functor laws). I realize that "useful but impure" vs "strictly correct" is an ongoing debate in Scala FP, but in this case I think that something like TryT really belongs in alley-cats.

All 3 comments

I'm happy to make a PR for this if I can get some +1s :)

Just to play devil's advocate here… What would the semantics of this be? Try catches in map/flatMap, would TryT as well? Try really isn't that different from Either[Throwable, ?], except that it pretends to be a Sync in some ways by catching exceptions, so isn't it correct that the only way to use it in higher level abstractions is to go through Either?

I understand that Try is used a lot, but I'd be really leery of trying to do something like a monad transformer for a monad that isn't really a monad (it violates the functor laws if you throw, which is the whole point of using Try in the first place, so it most definitely violates the functor laws). I realize that "useful but impure" vs "strictly correct" is an ongoing debate in Scala FP, but in this case I think that something like TryT really belongs in alley-cats.

Ah, I didn't actually know Try's map catches as well. I agree that making a transformer would have unclear semantics, and going through Either is probably best in this case. Thanks for discussion!

Was this page helpful?
0 / 5 - 0 ratings