There should be no need whatsoever for implicits if all you want is an extractor.
To define an extractor, you make an object
with an unapply
method. E.g.
object MyExtractor {
def unapply(value: ValueBeingMatched): Option[ExtractedValue] = { ... }
}
Then you match a value using the extractor
val myValue: ValueBeingMatched = ...
myValue match {
case MyExtractor(extractedValue) => println(s"I got $extractedValue!")
}
If you want your extractor to come back with multiple values, the unapply should return an option of tuple:
object MyExtractor {
def unapply(value: ValueBeingMatched): Option[(ResultType1, ResultType2, ...)] = { ... }
}
val myValue: ValueBeingMatched = ...
myValue match {
case MyExtractor(result1, result2, ...) => ...
}
I'm not clear on what you are trying to accomplish from your example code, so I'll make an example that maybe is relevant for you.
Let's say you make a custom Point
class:
case class Point(x: Int, y: Int)
And you want to be able to extract points from a String
. In this case, the ValueBeingMatched
is a String
, and the ExtractedValue
is a Point
. I'll also define the extractor in the Point
object. As for functionality, let's assume that a string like "12,8"
corresponds to a Point(12, 8)
.
object Point {
def unapply(s: String): Option[Point] = {
val parts = s.split(",")
// this is just example code, so I won't handle failures,
// but if it did fail, you'd return a None instead of Some
Some(Point(parts(0).toInt, parts(1).toInt))
}
}
Now that it's defined, you can match strings using the Point
extractor:
val s = "3,4"
s match {
case Point(p) => // p is actually an instance of Point
}
edit to respond to feedback:
In order to match directly to a string, the value being matched must already be a String. So one way would be to add a converter method e.g.
instanceOfMyType.convertToString match {
case "abc" => println("Aha!")
}
Or you would have to write an extractor to allow
instanceOfMyType match {
case Extracted("abc") => println("Aha!")
}