Scala has a nice feature to infer type parameter inside the pattern match. It also checks pattern match exhaustiveness. For example:
sealed trait PField[T]
cas
All your cases that extend Field
are singleton objects, so that for each subtype F
of Field
it holds:
if
a: F, b: F, b.T = X
then
a.T = X
This does not hold in general, for example for
class Bar { type Q }
case class Field3(b: Bar) extends Field { type T = b.Q }
it does not hold that a.T = b.T
for any two values a, b
of type Field3
.
So, you have to somehow guarantee that all subclasses of Field
are well-behaved like Field1
and Field2
, and that they are not like hypothetical Field3
. You can do this by adding an implicit argument to getValue
that acts as a proof that the field is well behaved. For example, proving that the field is indeed a singleton object would be sufficient.
Here is a rough sketch:
sealed trait Field { type T }
case object Field1 extends Field { type T = String }
case object Field2 extends Field { type T = Int }
sealed trait UniqGuarantee[UniqueTypeAsPathDependent]
case class S1UG[X](f: String =:= X) extends UniqGuarantee[X]
case class S2UG[X](f: Int =:= X) extends UniqGuarantee[X]
sealed trait IsSingleton[F <: Field] {
def apply(singleton: F): UniqGuarantee[singleton.T]
}
implicit object F1_is_Singleton extends IsSingleton[Field1.type] {
def apply(singleton: Field1.type): UniqGuarantee[singleton.T] =
S1UG(implicitly)
}
implicit object F2_is_Singleton extends IsSingleton[Field2.type] {
def apply(singleton: Field2.type): UniqGuarantee[singleton.T] =
S2UG(implicitly)
}
def getValue[F <: Field]
(f: F)
(implicit sing: IsSingleton[F])
: f.T = sing(f) match {
case S1UG(uniqGuarantee) => uniqGuarantee("abc")
case S2UG(uniqGuarantee) => uniqGuarantee(123)
}
This implementation does typecheck, and it also shows warnings if the pattern matching is non-exhaustive.
Admittedly, the solution is pretty heavyweight, because it requires that you implement an entire separate hierarchy of case classes and implicit objects that act as "proofs" that your Field
s are indeed singletons.
I think the solution could be shortened quite a bit, I just don't see how right now.