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

时间:2017-09-17 12:11:41

标签: scala

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

在SI-2712(https://issues.scala-lang.org/browse/SI-2712)之后,修正类型A被推断为最右边的类型参数。在我的Function1 [Int,String]的例子中,它是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]))

它仍然被推断为String而不是Int

1 个答案:

答案 0 :(得分:3)

编译器更喜欢尽可能扩展不具有稳定名称的类型(我不知道其中的理由,抱歉),因此在调用{{{}之前简化了返回点的类型lambda 1}}。好消息是,您可以利用统一优势来概括它:

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],这是您的类型构造函数的左参数