Here is a simple example:
trait RRBound {
type RR[T]
def apply[T]: T => RR[T]
}
trait Z2 extends RRBound {
type RR[T] = T match {
case Option[i] => Seq[i]
}
override def apply[T]: T => RR[T] = T match {
case Option[i] => (v: Option[i]) => v.toSeq
// invalid syntax here
}
}
trait AlsoZ2 {
def apply[i]: Option[i] => Seq[i] = {v => v.toSeq}
}
apparently T match
can only be used in type definition, so the only way to implement apply[T]: T => RR[T]
is by doing it in multiple subtypes, this also means Z2 cannot be converted to AlsoZ2 easily despite that they are functionally identical.
What can be done here to complete Z2 and make AlsoZ2 unnecessary?
Can you make apply
inline?
trait RRBound {
type RR[T]
inline def apply[T]: T => RR[T]
}
Try
import scala.compiletime.{erasedValue, summonFrom}
override inline def apply[T]: T => RR[T] = (v: T) => summonFrom {
case given (T =:= Option[i]) => summonFrom {
case given (Seq[`i`] =:= RR[T]) => (v: Option[`i`]).toSeq
}
}
or
override inline def apply[T]: T => RR[T] = (v: T) => erasedValue[T] match {
case _: Option[i] => summonFrom {
case given (T =:= Option[`i`]) => (v: Option[`i`]).toSeq
}
}