如何隐含地将类型投影转换为 PDT?
How to translate type projections into PDTs in implicits?
这是一个惯用的 Scala 2 示例:
trait Box {
type Content
val content :Content
}
implicit class BoxExtension[B <: Box](private val self :B) extends AnyVal {
def map[O](f :self.Content => O)(implicit mapper :Mapper[B, O]) :mapper.Res =
mapper(self)(f)
}
trait Mapper[B <: Box, O] {
type Res
def apply(box :B)(f :box.Content => O) :Res
}
如您所见,它已经部分转换为使用路径依赖类型。但是如何为引用 self.Content
的 O
类型(例如 O =:= self.Content
本身)创建隐式值 Mapper
?理想情况下,Scala 2 和 Scala 3 之间具有直接等价性的解决方案。
你可以为此做一个隐式定义。由于 Dotty 不允许对抽象类型进行类型投影,因此您需要一个额外的类型参数。另外,我必须制作 self
public 因为它被用在 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
和(Mapper
的额外类型参数)代替,但它得到 little complicated. Perhaps you could turn BoxExtension
into something like this,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 而不是 cross-compiling,您可以 this
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))
}
}
这是一个惯用的 Scala 2 示例:
trait Box {
type Content
val content :Content
}
implicit class BoxExtension[B <: Box](private val self :B) extends AnyVal {
def map[O](f :self.Content => O)(implicit mapper :Mapper[B, O]) :mapper.Res =
mapper(self)(f)
}
trait Mapper[B <: Box, O] {
type Res
def apply(box :B)(f :box.Content => O) :Res
}
如您所见,它已经部分转换为使用路径依赖类型。但是如何为引用 self.Content
的 O
类型(例如 O =:= self.Content
本身)创建隐式值 Mapper
?理想情况下,Scala 2 和 Scala 3 之间具有直接等价性的解决方案。
你可以为此做一个隐式定义。由于 Dotty 不允许对抽象类型进行类型投影,因此您需要一个额外的类型参数。另外,我必须制作 self
public 因为它被用在 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
和(Mapper
的额外类型参数)代替,但它得到 little complicated. Perhaps you could turn BoxExtension
into something like this,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 而不是 cross-compiling,您可以 this
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))
}
}