类型构造函数推理的高阶统一


def meh[M[_], A](x: M[A]): M[A] = x
meh((x: Int) => "")

SI-2712(https://issues.scala-lang.org/browse/si-2712)fix a类型A被推断为最右键的参数。在我的function1 [int,string]的示例中,它是字符串。

如何将其推断为左参数?

为什么这种方法不起作用?

class T[K,M]{}
def inferToLeft[S[_,_],K,B](ot: S[K,B]):({type Op[T] = S[T,B]})#Op[K]= ot
meh(inferToLeft(new T[Int,String]))

它仍然推断为字符串而不是int

编译器更喜欢扩展没有稳定名称的类型(我不知道为此的理由,对不起),因此您的类型lambda在返回点上进行了简化致电meh。好消息是,您可以利用统一来概括它:

import scala.reflect.runtime._, universe._
import scala.language.higherKinds
def checkUnification[F[_], A: TypeTag](fa: => F[A]) = s"${typeOf[A]}"
implicit class InferToLeft[M[_, _], A, B](a: M[A, B]) {
  def lefty: InferToLeft.U[M, B, A] = a
}
object InferToLeft {
  type U[M[_, _], B, A] = M[A, B]
}
def e: Either[Int, String] = ???
def f: AnyRef => List[Int] = ???
assert(checkUnification(e) == "String")
assert(checkUnification(e.lefty) == "Int")
assert(checkUnification(f) == "scala.List[Int]")
assert(checkUnification(f.lefty) == "AnyRef")

在这里,InferToLeft.U类型可在稳定路径上找到,因此您的参数以U[M, B, A]的形式传递,而无需简化,使统一选择A,这是您类型构造函数的左参数。

最新更新