'Pattern matching for headOption with enum

The problem I'm trying to solve is to check if the first element (if any) of a list is of a certain enum type. As follows:

enum Color(val rgb: Int):
  case Red   extends Color(0xFF0000)
  case Green extends Color(0x00FF00)
  case Blue  extends Color(0x0000FF)
  case CustomColor(override val rgb: Int) extends Color(rgb)



def isExpected(expect: Color, colors: List[Color]): Either[Error, (Color, List[Color])] =
  colors.headOption match {
    case Some(head) => {
      if (head == expect) { Right(expect, tokens.tail) }
      else {
        expect match {
          case Color.Red => Left(Error.ExpectRed)
          case Color.Green => Left(Error.ExpectGreen)
          case Color.Blue => Left(Error.ExpectBlue)
        }
      } 
    }
    case _ => {
      expect match {
          case Color.Red => Left(Error.ExpectRed)
          case Color.Green => Left(Error.ExpectGreen)
          case Color.Blue => Left(Error.ExpectBlue)
      }
    }
  }
  1. Is there a way to refactor the duplicated code in the above snippet?
  2. Is it possible to check if the type of headOption matches the expect parameter even in the first case condition?


Solution 1:[1]

How about this:

scala> enum Color(val rgb: Int):
     |   case Red   extends Color(0xFF0000)
     |   case Green extends Color(0x00FF00)
     |   case Blue  extends Color(0x0000FF)
     |   case CustomColor(override val rgb: Int) extends Color(rgb)
     |
     | enum Error:
     |   case ExpectRed
     |   case ExpectGreen
     |   case ExpectBlue
     |   case ExpectCustom
     |
     |
     | def isExpected(expect: Color, colors: List[Color]): Either[Error, (Color, List[Color])] = colors match
     |   case `expect` :: tail => Right(expect, tail)
     |   case _                =>
     |     expect match
     |       case c: Color.CustomColor => Left(Error.ExpectCustom)
     |       case rgb                  => Left(Error.valueOf(s"Expect$rgb"))
     |
// defined class Color
// defined class Error
def isExpected
  (expect: Color, colors: List[Color]): Either[Error, (Color, List[Color])]

scala> val colors = List(Color.Red, Color.Green, Color.CustomColor(123))
val colors: List[Color] = List(Red, Green, CustomColor(123))

scala> isExpected(Color.Green, colors)
val res0: Either[Error, (Color, List[Color])] = Left(ExpectGreen)

scala> isExpected(Color.Red, colors)
val res1: Either[Error, (Color, List[Color])] = Right((Red,List(Green, CustomColor(123))))

scala> isExpected(Color.CustomColor(123), colors)
val res2: Either[Error, (Color, List[Color])] = Left(ExpectCustom)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eastsun