headOption 与枚举的模式匹配

Pattern matching for headOption with enum

我要解决的问题是检查列表的第一个元素(如果有的话)是否属于某种枚举类型。如下:

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. 有没有办法重构上面代码段中的重复代码?
  2. 是否可以检查 headOption 的类型是否与 expect 匹配 参数甚至在第一种情况下?

这个怎么样:

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)