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))
}
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!
Most helpful comment
Just to play devil's advocate here… What would the semantics of this be?
Trycatches inmap/flatMap, wouldTryTas well?Tryreally isn't that different fromEither[Throwable, ?], except that it pretends to be aSyncin some ways by catching exceptions, so isn't it correct that the only way to use it in higher level abstractions is to go throughEither?I understand that
Tryis 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 youthrow, which is the whole point of usingTryin 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 likeTryTreally belongs in alley-cats.