E108: Unapply Invalid Return Type
This error is emitted when an extractor's unapply or unapplySeq method has an invalid return type.
To be used as an extractor, an unapply method must return a type that either:
- Has members
isEmpty: Booleanandget: S(usually anOption[S]) - Is a
Boolean - Is a
Product(like aTuple2[T1, T2])
Example
object MyExtractor:
def unapply(s: String): String = s
def example(s: String) = s match
case MyExtractor(_) => "ok"
case _ => "no match"
Error
-- [E108] Declaration Error: example.scala:5:18 --------------------------------
5 | case MyExtractor(_) => "ok"
| ^^^^^^^^^^^^^^
| String is not a valid result type of an unapply method of an extractor.
|-----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| To be used as an extractor, an unapply method has to return a type that either:
| - has members isEmpty: Boolean and get: S (usually an Option[S])
| - is a Boolean
| - is a Product (like a Tuple2[T1, T2]) of arity i with i >= 1, and has members _1 to _i
|
| See: https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors
|
| Examples:
|
| class A(val i: Int)
|
| object B {
| def unapply(a: A): Option[Int] = Some(a.i)
| }
|
| object C {
| def unapply(a: A): Boolean = a.i == 2
| }
|
| object D {
| def unapply(a: A): (Int, Int) = (a.i, a.i)
| }
|
| object Test {
| def test(a: A) = a match {
| case B(1) => 1
| case a @ C() => 2
| case D(3, 3) => 3
| }
| }
|
-----------------------------------------------------------------------------
Solution
// Return Option[T] for single value extraction
object MyExtractor:
def unapply(s: String): Option[String] = Some(s)
def example(s: String) = s match
case MyExtractor(x) => x
case _ => "no match"
// Or return Boolean for test-only extraction
object IsEmpty:
def unapply(s: String): Boolean = s.isEmpty
def example(s: String) = s match
case IsEmpty() => "empty"
case _ => "not empty"
// Or return a tuple for multiple values
object Split:
def unapply(s: String): Option[(String, String)] =
val mid = s.length / 2
Some((s.take(mid), s.drop(mid)))
def example(s: String) = s match
case Split(a, b) => s"$a | $b"
case _ => "no match"
In this article