using Try in flatMap

Viewed 139

Im writing my own class Success or Error. I want to create a way to build SuccessOrError from Try and then use Try instead of ugly try-catch in flatMap. But I'm stuck at this point. How should I best write a function fromTry in order to be able to write like this?
case SuccessOrError.Success(v) ⇒ SuccessOrError.fromTry(Try(f(v)))

  enum SuccessOrError[+V]:

    case Success(x: V) extends SuccessOrError[V]

    case Error(e : Throwable) extends SuccessOrError[V]

    def flatMap[Q](f: V ⇒ SuccessOrError[Q]): SuccessOrError[Q] =
      this match
        case SuccessOrError.Success(v)   ⇒ try f(v) catch case NonFatal(e) => SuccessOrError.Error(e) 
        case SuccessOrError.Error(e)  ⇒ SuccessOrError.Error(e)


object SuccessOrError:
   def fromTry[Q](f: Try[Q]): SuccessOrError[Q] = ???
1 Answers

Converting from Try to another error model is quite a common practice. Perhaps consider how they approach it in scala-cats library as inspiration

Validated

  /**
   * Converts a `Try[A]` to a `Validated[Throwable, A]`.
   */
  def fromTry[A](t: Try[A]): Validated[Throwable, A] =
    t match {
      case Failure(e) => invalid(e)
      case Success(v) => valid(v)
    }

or Either

  /**
   * Converts a `Try[A]` to a `Either[Throwable, A]`.
   */
  def fromTry[A](t: Try[A]): Either[Throwable, A] =
    t match {
      case Failure(e) => left(e)
      case Success(v) => right(v)
    }

or ApplicativeError

  /**
   * If the error type is Throwable, we can convert from a scala.util.Try
   */
  def fromTry[A](t: Try[A])(implicit ev: Throwable <:< E): F[A] =
    t match {
      case Success(a) => pure(a)
      case Failure(e) => raiseError(e)
    }

Note the pattern (bad pun, applogies) of simply pattern matching on happy and unhappy cases, so we can try emulating it

def fromTry[Q](f: Try[Q]): SuccessOrError[Q] = 
  f match {
    case scala.util.Failure(e) => SuccessOrError.Error(e)
    case scala.util.Success(v) => SuccessOrError.Success(v)
  }
Related