您可以为此创建一个隐式定义。由于 Dotty 不允许对抽象类型进行类型投影,因此您需要一个额外的类型参数。另外,我不得不self
公开,因为它被用于map
.
object Mapper {
implicit def uselessMapper[B <: Box{type Content = C}, C]: Mapper[B, C] { type Res = AllPurposeBox[C] } =
new Mapper[B, C] {
type Res = AllPurposeBox[C]
def apply(box: B)(f: box.Content => C) =
new AllPurposeBox(f(box.content))
}
}
class AllPurposeBox[T](override val content: T) extends Box {
type Content = T
}
完整示例
我通常建议将类型参数用于Box
and (以及一个额外的用于Mapper
),但它会变得有点复杂。也许你可以变成这样BoxExtension
的东西,作为一个额外的参数:C
implicit class BoxExtension[B <: Box {type Content = C}, C](private val self: B) extends AnyVal {
def map[O](f: C => O)(implicit mapper: Mapper[B, O]): mapper.Res =
mapper(self)(f)
}
如果你愿意只使用 Dotty 而不是交叉编译,你可以这样做
trait Mapper[B <: Box, O] {
type Res
def apply(box: B)(f: box.Content => O): Res
extension (self: B) def map(f: self.Content => O): Res = apply(self)(f)
}
object Mapper {
given uselessMapper[B <: Box{type Content = C}, C] as Mapper[B, C] {
type Res = AllPurposeBox[C]
def apply(box: B)(f: box.Content => C) = new AllPurposeBox(f(box.content))
}
}