Scala: Verify Unique Type Existence At Compile Time

63 Views Asked by At

I have the following:

sealed trait Tag
case object MyTag1 extends Tag
case object MyTag2 extends Tag

sealed trait Error[T <: Tag]

// error implementations...

I'd like for two Error implementations using the same Tag to fail at compile time, but not fail in the case there are Tags without an associated Error.

The compilation guard given in the first answer here: How can I verify type existence on compile time in Scala comes very close to what I want, but fails at compile time if there exists a Tag without an associated Error.

1

There are 1 best solutions below

0
Dmytro Mitin On BEST ANSWER

You can try to add one more case to the Poly

def compilationGuard[C <: Coproduct]()(implicit
  gen: Generic.Aux[Signal, C],
  mapper: Mapper[uniqueDescriptionPoly.type, C]
) = null

object uniqueDescriptionPoly extends Poly1 {
  implicit def cse[S <: Signal, C1 <: Coproduct](implicit
    gen1: Generic.Aux[Description[S], C1],
    ev: C1 <:< (_ :+: CNil)
  ): Case.Aux[S, Null] = null

  implicit def cse0[S <: Signal, C1 <: Coproduct](implicit
    gen1: Refute[Generic[Description[S]]]
  ): Case.Aux[S, Null] = null
}

compilationGuard()
final case class S1(name: String) extends Signal
final case class S2(name: String) extends Signal
final case class D1(name: String) extends Description[S1]
//compiles
final case class S1(name: String) extends Signal
final case class S2(name: String) extends Signal
final case class D1(name: String) extends Description[S1]
final case class D2(name: String) extends Description[S1]
// doesn't compile
final case class S1(name: String) extends Signal
final case class S2(name: String) extends Signal
final case class D1(name: String) extends Description[S1]
final case class D2(name: String) extends Description[S2]
// compiles