首页 > 解决方案 > Scala 隐式泛型类型自动推断

问题描述

我想构建一个转换方法以通过构建器输出特定类型,但根据情况,最后一个是否采用隐式位置将修改泛型类型自动推断。我很乐意了解更多有关的好奇行为。

trait Wrap[A]

trait Toto[A, W <: Wrap[A]] {

    def fail[A2, W2 <: Wrap[A2], T2 <: Toto[A2, W2]](f: W => W2)(implicit builder: Builder[A2, W2, T2]): T2
    def works[A2, W2 <: Wrap[A2], T2 <: Toto[A2, W2]](f: W => W2, builder: Builder[A2, W2, T2]): T2
}

trait Builder[A, W <: Wrap[A], T <: Toto[A, W]]


type A1
type W1 <: Wrap[A1]
type A2
type W2 <: Wrap[A2]
type T2 <: Toto[A2, W2]

val t1: Toto[A1, W1]
implicit val builder: Builder[A2, W2, T2]
val f: W1 => W2


t1.fail(f) // inferred type arguments [Nothing, W2, Nothing] do not conform to method fail's type parameter
    
t1.fail(f)(builder) // inferred type arguments [Nothing, W2, Nothing] do not conform to method fail's type parameter
/**
 * [error]  found   : Test.this.W1 => Test.this.W2
 * [error]  required: Test.this.W1 => W2
 */

 t1.works(f, builder) // compiles



标签: scalatype-inferenceimplicit

解决方案


事情不是隐含的。如果你works用两个参数列表重写

def works1[A2, W2 <: Wrap[A2], T2 <: Toto[A2, W2]](f: W => W2)(builder: Builder[A2, W2, T2]): T2

这也行不通。如果fbuilder在同一个参数列表中,那么在

t1.works(f, builder)

A2, W2, T2是推断出来的,但是如果f在第一个参数列表中并且builder在第二个参数列表中,那么在

t1.works1(f)(builder)
//          ^
//         here

f仅从第一个参数列表W2中推断正确,因此A2推断T2Nothing,然后在第二个参数列表的类型检查期间返回并修复推断为时已晚,并且失败了。

Scala 类型推断和多参数列表

具有类型别名和多参数列表功能的类型推断

Scala - 推断类型参数

所以如果你想使用隐式builder(然后你不能使用单个参数列表)尝试重写你的代码。尝试用隐式约束替换类型边界(这会改变类型推断的顺序),然​​后你必须用抽象类替换特征,以便它们可以具有隐式参数

trait Wrap[A]

abstract class Toto[A, W](implicit ev: W <:< Wrap[A]) { 
  def fail1[A2, W2, T2](f: W => W2)(implicit builder: Builder[A2, W2, T2], ev1: W2 <:< Wrap[A2], ev2: T2 <:< Toto[A2, W2]): T2
}

abstract class Builder[A, W, T](implicit ev: W <:< Wrap[A], ev1: T <:< Toto[A, W])

t1.fail1(f) //compiles

推荐阅读