Reputation: 1516
I have an enum for keywords and operators (and some other too), e.g. (all are similar):
object Keywords extends Enumeration {
val AND, ARRAY, BEGIN, ...= Value
case class Keyword(keyword: Value) extends Token[Value] {
def this(keyword: String) = this(Keywords.fromString(keyword))
def value = keyword
}
implicit def valueToKeyword(keyword: Value) = new Keyword(keyword)
}
this implicit conversion allows me to pass enum values where Token
s are expected e.g.
def testFunction[T](t: Token[T]) = ...
testFunction(Keywords.ARRAY) // gets converted
testFunction(Operators.PLUS) // gets converted too
it also seems that the same implicit conversion is not applied during matching i.e.
val token = new Keyword("ARRAY")
token match {
case Keywords.ARRAY => ... // not selected but SHOULD be
case Operators.PLUS => ... // completely different Enum
...
}
Why? How to overcome this?
Upvotes: 8
Views: 1898
Reputation: 4966
This doesn't work because:
token match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
is essentially a PartialFunction with the following type signature: PartialFunction[Keywords.Value, Unit]
. Which means an implicit won't be applied, because it's either isDefinedAt or it isn't for that input.
If it isn't defined than case _ => ...
will catch everything in my example code. If it's not defined at all and nothing will match it then you will get a MatchError thrown.
In your case token
of type Token[Value]
isn't defined in the Partial Function that the match will compile to, because only types of Keywords.Value
are defined.
If you really want implicits then you could explicitly ask for an implicit (yes, that sentence is funny :))
implicitly[Keywords.Value](token) match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
Or you can explicitly state the type of token
, to invoke the implicit magic:
val token: Keywords.Value = new Keyword("ARRAY")
token match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
Or the simplest solution if you can live without implicits:
token.value match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
I know it's not the answer you're looking for, but I hope that you understood what match {...}
really means and what Partial Functions are.
Upvotes: 5