Reputation: 1312
Exhaustive pattern matching is great, but it only appears to work on the left-hand side of the case (=>
) operator.
I am curious if there is a way that a person can verify that the output of a function (or expression) can be bound to that enumeration. The goal would be to have the compiler tell me when I forget to output an item from the enumeration.
In my example, I make use of the following enumeration containing three items:
object MyEnum {
sealed trait t
case object E1 extends t
case object E2 extends t
case object E3 extends t
}
And here is a pattern-match expression that would produce a compile-time warning (as we already know):
def foo( e : MyEnum.t ) : Boolean =
e match {
case MyEnum.E1 => true
case MyEnum.E2 => false
case MyEnum.E3 => true // if we leave this line out, we get a warning
}
Scala would complain if we left MyEnum.E3
out of the pattern matching expression, citing a non-exhaustive pattern match. This is profoundly beneficial, but I wonder if the reverse is possible.
Can we account for all cases of MyEnum.t
on the right-hand side of =>
?
Here is an example that highlights this:
def bar( s : String ) : Option[MyEnum.t] =
s match {
case "a" => Some(MyEnum.E1)
case "b" => Some(MyEnum.E2)
case "c" => Some(MyEnum.E3) // if we leave this out, no warning
case _ => None
}
In this example, if we leave out the line with MyEnum.E3
, then the compiler just carries on as if nothing is wrong. The assertion I would like to make, is:
forall MyEnum.t (aliased as e) there exists Some(e) | None
I understand that this could be easily covered by a run-time test, but I'm curious if there is a way to check this statically.
Thanks.
Upvotes: 3
Views: 221
Reputation: 33063
No, it is not possible, because this is equivalent to the Halting Problem, which was proven unsolvable in 1936.
Upvotes: 0
Reputation: 12745
I am going to push my luck and claim it is not possible (let's keep this a secret from Odersky). If the Scala compiler was able to detect such situations, I think it would be even slower than it already is ;)
The only way I could see is to define foo similarly to how you have done, and define bar by making it iterate over foo to make a reverse map, but that doesn't make much sense to me, and might not work in your specific case.
I think your case is a very good example for when unit tests are useful, so why not just write one?
Upvotes: 0