Scala's Nothing vs partial unification

て烟熏妆下的殇ゞ 提交于 2021-02-08 06:38:34

问题


I would expect the following code to compile just fine:

trait Widen[M[_]] { def widen[A, B >: A](ma: M[A]): M[B] }

object Widen {
  implicit class Ops[M[_], A](ma: M[A]) {
    def widen[B >: A](implicit ev: Widen[M]): M[B] = ev.widen[A, B](ma)
  }
  // implicit class OpsNothing[M[_]](ma: M[Nothing]) {
  //   def widen[B](implicit ev: Widen[M]): M[B] = ev.widen(ma)
  // }
  implicit val WidenList = new Widen[List] { def widen[A, B >: A](l: List[A]): List[B] = l }
}

import Widen._

List.empty[Some[Int]].widen[Option[Int]]

List.empty[Nothing].widen[Int] // does not compile until uncommenting OpsNothing

But the last line does not compile. It seems to be related to partial unification because new Widen.Ops[List, Nothing](List.empty[Nothing]).widen[Int] does compile.

Now what's really weird is that if I uncomment the special case for Nothing then everything compiles.

I have no idea what's going on...

(This is using Scala 2.13.3)


回答1:


Compiler doesn't like to infer Nothing while resolving implicits

Failed implicit resolution for Nothing with <:<

Another workaround besides OpsNothing is type Bottom

type Bottom <: Nothing
List.empty[Bottom].widen[Int] // compiles


来源:https://stackoverflow.com/questions/63642765/scalas-nothing-vs-partial-unification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!