Report a status based on a list of results In one of my services, I have the function as presented below:

private def convertCreateResultsToCreateAllReasult(results: List[CreateResult.Result]): CreateAllResult.Result = {
    val firstConflictResult = results.collectFirst {
      case r: CreateResult.Conflict =&gt; r
    } match {
      case Some(cr: CreateResult.Conflict) =&gt; Some(CreateAllResult.Conflict(cr.message))

      case None =&gt; None
    }

    val firstNotFoundResult = results.collectFirst {
      case r: CreateResult.NotFound =&gt; r
    } match {
      case Some(nfr: CreateResult.NotFound) =&gt; Some(CreateAllResult.NotFound(nfr.message))

      case None =&gt; None
    }

    val firstFailedResult = results.collectFirst {
      case r: CreateResult.Failed =&gt; r
    } match {
      case Some(fr: CreateResult.Failed) =&gt; Some(CreateAllResult.Failed(fr.message))

      case None =&gt; None
    }

    val failedResults = List(firstConflictResult, firstNotFoundResult, firstFailedResult).flatten

    if (failedResults.isEmpty) {

      val createdDefinitions = results.collect {
        case r: CreateResult.Ok =&gt; r.definition
      }

      CreateAllResult.Ok(createdDefinitions)

    } else {

      failedResults.head

    }
  }


The argument of this function is a list of result objects, where the result object looks like this:

object CreateResult {

    sealed trait Result

    case class Ok(definition: ChecklistRuleDefinition) extends Result
    case class Conflict(message: String) extends Result
    case class NotFound(message: String) extends Result
    case class Failed(message: String) extends Result

  }


As you can see the result can be Ok (which is considered successful) and everything else (that considered as failed for various reasons).

The function should:


Return first fails result converted into a different type in case there is one such result in the list.
or
Return all successful results converted into CreateAllResult.Ok (if all of them successful).


Here is the CreateAllResult object:

object CreateAllResult {

    sealed trait Result

    case class Ok(definitions: List[ChecklistRuleDefinition]) extends Result
    case class Conflict(message: String) extends Result
    case class NotFound(message: String) extends Result
    case class Failed(message: String) extends Result

  }


The thing is, whatever I posted here, it seems to be working as expected. But, I hate the code. I know know that scala has all the bells and whistles to make the code nicer and more readable. I just didn't find the way to do so.

How can this code be written in a nicer, scala like, way?
Something like this maybe?

  @tailrec
  def trf(
    results: List[CreateResult.Result],
    conf: Option[CreateAllResult.Conflict] = None,
    nf:   Option[CreateAllResult.NotFound] = None, 
    f:    Option[CreateAllResult.Failed] = None, 
    defs: List[ChecklistRuleDefinition] = Nil
  ): List[CreateAllResult.Result] = results.map { 
    case r: CreateResult.Conflict :: tail if conf.isEmpty =&gt; 
         trf(tail, Some(CreateAllResult.Conflict(r)), nt, f, Nil)
    case r: CreateResult.NotFound :: tail if nf.isEmpty  =&gt; 
         trf(tail, conf, Some(CreateAllResult.NotFound(r)), f, Nil)
    case r: CreateResult.Failed  if f.isEmpty =&gt; 
         trf(tail, conf, nf, Some(CreateAllResult.Failed(r)), Nil)
    case Ok(defn) :: tail if conf ++ nf ++ f isEmpty =&gt; 
         trf(tail, None, None, None, dfn :: defs)
    case _ if defs.isEmpty =&gt; conf ++ nf ++ f
    case _ =&gt;  CreateAllResult.Ok(defs.reverse)
  }


Oh, wait you are only returning the first failure, are you? I didn't realize that at first, thought you wanted the first of each type. 
Well, that makes it kinda simpler ... 
How about this: 

object Failure {
   def unapply(res: Result) = res match {
    case r: CreateResult.Conflict  =&gt; Some(CreateAllResult.Conflict(r))
    case r: CreateResult.NotFound  =&gt; Some(CreateAllResult.NotFound(r))
    case r: CreateResult.Failed =&gt; Some(CreateAllResult.Failed(r))
   } 
}

def trf(results: List[CreateResult.Result]) = results
  .collectFirst { case Failure(r) =&gt; r }
  .getOrElse(CreateAllResult.Ok(
     results.collect { case r: CreateResult.Ok =&gt; r.definition }
   ))