如何解决如何将类型投影转换为隐式的PDT?
这是一个惯用的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
}
如您所见,它已经部分转换为依赖于路径的类型。但是,如何为引用了Mapper
的{{1}}类型(例如O
本身)创建self.Content
的隐式值呢?理想情况下,在Scala 2和Scala 3之间具有直接等效的解决方案。
解决方法
您可以为此进行隐式定义。由于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
和{(对于Mapper
使用附加参数),但是它会得到little complicated。也许您可以将BoxExtension
转换成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而不是交叉编译,则可以进行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))
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。