方法调用的延迟类型推断

时间:2013-08-12 08:05:00

标签: scala type-inference implicit

我正在阅读Josh Suereth的(好)帖A Generic Quicksort in Scala。特别有趣的是关于延迟收集的类型推断的部分。

现在我想知道这是否也适用于非收藏品。以下两种方法创建Foo[T,O]

def sort1[T, O](from: T, to: T)(implicit ev: O <:< Ordering[T], ord: O):Foo[T,O] = {
   ...
}

def sort2[T, O <: Ordering[Int]](from: T, to: T)(implicit ord: O):Foo[T,O] = {
   ...
}

这两种方法中哪一种更受欢迎?为什么?

sort2(2,5)确实有效,sort1(2,5)编译器似乎发现更多隐含,因为存在模糊的隐式解析错误。

2 个答案:

答案 0 :(得分:1)

实际上,这似乎不直观。

原因是sort1没有对O定义约束,因此'ord:O'是不明确的。 (第一个隐式参数的约束只定义了'ev'类型的约束。)

希望有所帮助:)

答案 1 :(得分:1)

使用generalized type constraints推迟类型推断是关于绕过类型推断的限制。这些限制不一定是错误,它们可以是设计的。

我可以想到它们有用的两种常见情况:

  • 你想把这个类型放在另一个更高级别的类型中,但你没有约束力来获得它。

    示例:

    def sort[T, Coll <: SeqLike[T, Coll](a: Coll): Coll
    

    编译器无法获取类型参数T,因为它不以任何方式约束:它不会出现在<:>:的左侧在类型参数列表中,并不出现在参数的类型中。

    广义类型约束允许在此约束(通过参数)类型T

    def sort[T, Coll](a: Coll)(implicit ev: Coll <:< SeqLike[T, Coll]): Coll
    

    注意:这只是一种方法。通常有一种方法可以让同样的东西 非常接近而没有隐含的证据。这将是:

    def sort[T, Coll <: SeqLike[T, Coll]](a: Coll with SeqLike[T, Coll]): Coll
    
  • 您无法控制类型参数,因为它来自封闭类。

    例如,在flatten上添加List[A]方法仅在A为集合本身时才有效。您不能仅为该方法更改类型参数A,但可以使用implicit ev: A <:< Traversable[B]或类似的方法在本地添加约束。

    注意2 :这不是在使用implicit ev: (A) => Traversable[B]的集合库中完成的操作,因此可以转换为集合的任何内容都可以工作(如{{1} }或String),但有时你不希望这样。

修改以解决Array vs sort1问题:在不需要时添加通用类型约束可能会产生此类错误,因为类型变得不受约束。由于sort2中的O没有约束,sort1可以是任何内容。隐式证据只能用于在方法体内查看ord: O O

如果你真的想保留隐含证据,你必须在某处重新引入一些约束。关于类型参数,例如Ordering[T]sort2本身:

ord

在这种情况下,def sort3[T, O](from: T, to: T) (implicit ev: O <:< Ordering[T], ord: O with Ordering[T]):Foo[T,O] 似乎是最好的方法。