Search code examples
scalapattern-matchingfor-comprehension

Scala extract the parameter in for comprehension when match multiple cases classes


I'm having a sealed trait implementation with multiple case classes, each case class has its own parameters, some of them have the same type of param (which I want to extract, in this case: Trigger), some of them don't.

sealed trait Event

object MyTrait {
  final case class EventA(context: Context) extends Event

  final case class EventB(trigger: Trigger) extends Event

  final case class EventC(trigger: Trigger) extends Event

  final case class EventD(trigger: Option[Trigger] = None) extends Event

  ...

  final case class EventZ(factor: Factor) extends Event

}

The logic flow is being handled as following:

event match {
 case ev @(_: Event.EventA | _: Event.EventB |
      _: Event.EventC | _: Event.EventD) =>
   val amount = for {
     count1 <- countThis
     count2 <- countThat
     // My logic added here
     _      <- handleSomeTypeOfEvent(ev.trigger)  // Doesn't work due to difference in implementations of event types
   } yield res + another

 case _ => doSomethingElse()
}

I need to add a function into the for comprehension and that function need a Trigger as a parameter. But in the match case, not all events contain Trigger parameter, EventD even has it in the form of an Option[].

Is there any solution to resolve this without decoupling event type match and duplicate the for comprehension logic for each case?


Solution

  • I think you could add extractTrigger function and change signature of handleSomeTypeOfEvent to accept Option[Trigger] values:

    def extractTrigger(event: Event): Option[Trigger] =
      event match {
        case EventB(trigger) => Some(trigger)
        case EventC(trigger) => Some(trigger)
        case EventD(trigger) => trigger
        case _               => None
    
      }
    
    def handleSomeTypeOfEvent(maybeTrigger: Option[Trigger]): String = ???
    
    val ev: Event = ???
    handleSomeTypeOfEvent(extractTrigger(ev))