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