scala - 方法调用时的延迟类型推断

标签 scala type-inference implicit

我正在阅读这篇(很棒的)帖子 A Generic Quicksort in Scala来自乔什·苏雷思。特别有趣的是关于延迟集合类型推断的部分。

现在我想知道这是否也适用于非集合。以下 2 个方法创建一个 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) 编译器似乎发现了更多隐式,因为存在不明确的隐式解析错误。

最佳答案

使用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] ,这样任何可以转换为集合的东西都可以工作(例如 StringArray ),但有时您不希望这样。

编辑以解决 sort1sort2问题:在不需要时添加广义类型约束可能会产生这种错误,因为类型变得约束不足。由于 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]

在本例中,sort2似乎是最好的方法。

关于scala - 方法调用时的延迟类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18182101/

相关文章:

Hibernate 3.5 与 4 IDENTITY_INSERT 问题

scala - 用 `type` 参数声明一个函数 `implicit`

scala - 是否有任何 Scala ORM 实现了从 SQL -> Scala 生成代码?

scala - PlayFramework:项目中的多个路由文件

scala - 访问(/导入)Scala 枚举

scala - 如何在此折叠示例中解决类型推断错误?

java - 为什么在使用有界类型参数时需要强制转换

haskell - TypeFamilies 或 GADT 突然破坏了有效代码

scala - scalaz.Equal 是如何解决的

scala - 将字符串格式设置为带有两位小数的浮点型