I'd like an extractor to implicitly convert its parameters, but it doesn't seem to work. Consider this very simple case:
case class MyString(s: String) {}
implicit def string2mystring(x: String): MyString = new MyString(x)
implicit def mystring2string(x: MyString) = x.s
object Apply {
def unapply(s: MyString): Option[String] = Some(s)
}
But I'm not able to use it as I would expect:
val Apply(z) = "a" // error: scrutinee is incompatible with pattern type
Can anyone explain why it fails to convert the parameter from String
to MyString
? I would expect it to call string2mystring("a")
on the fly. Clearly I could work around the issue by saying val Apply(y) = MyString("a")
, but it doesn't seem like I should have to do that.
Note: This question is similar to this one, but 1) that one doesn't really have a good answer for why this is happening, 2) the example is more complex than it needs to be.
Implicit conversions in Scala are the set of methods that are apply when an object of wrong type is used. It allows the compiler to automatically convert of one type to another. Implicit conversions are applied in two conditions: First, if an expression of type A and S does not match to the expected expression type B.
Whereas the apply method is like a constructor which takes arguments and creates an object, the unapply takes an object and tries to give back the arguments. This is most often used in pattern matching and partial functions. The apply method creates a CustomerID string from a name .
Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class's primary constructor available for implicit conversions when the class is in scope. Implicit classes were proposed in SIP-13.
With implicit request It allows to get an instance of Messages automatically (the compiler will implicitly call request2Messages(yourRequest) when needed but you need to have an implicit request (or request header) in scope.
Implicit conversions are not applied when pattern matching. That's not a bug or a problem with your code, it's simply a design decision of the creators of Scala.
To fix it, you should write another extractor that accepts a String
— which in turn can call your implicit conversion.
Alternatively, you can try with a view bound, which seems to work as well, and will also work if you later define other implicit conversions to MyString
:
object Apply {
def unapply[S <% MyString](s: S): Option[String] = Some(s.s)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With