Scala类型边界&方差

时间:2013-06-04 18:36:51

标签: scala generics types type-inference type-bounds

我正在努力更好地理解以下行为:

scala> class C[-A, +B <: A]
<console>:7: error: contravariant type A occurs in covariant position
                    in type >: Nothing <: A of type B
       class C[-A, +B <: A]
                    ^

然而,以下工作:

scala> class C[-A, +B <% A]
defined class C

我可以看到边界和有界变量的方差可能存在问题,尽管我不清楚具体问题是什么。 我更不清楚为什么更改绑定到视图绑定的类型会使事情变得正常。在没有适用的隐式转换的情况下,我希望这两个定义具有大致相同的效果。如果有什么我会期望一个观点必然会提供更多的恶作剧机会。

对于一些背景知识,我定义了类似函数的类,我想做类似的事情

CompositeFunc[-A, +B <: C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
  extends BaseFunc[A, D]

可以说是

CompositeFunc[-A, +B <% C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
  extends BaseFunc[A, D]

实际上更可取,但我仍然希望更好地了解这里发生了什么。

1 个答案:

答案 0 :(得分:4)

首先是简单的:

class C[-A, +B <% A]

这相当于

class C[-A, +B](implicit view: B => A)

由于view未公开返回,因此它不会限制AB的方差。 E.g。

class C[-A, +B](val view: B => A)  // error: B in contravariant position in view

换句话说,C[-A, +B <% A]在约束方面与C[-A, +B]没有区别,view参数不会改变任何内容。


上限情况C[-A, +B <: A]我不确定。 §4.5中的Scala语言规范指出

  

类型声明或类型参数的下限的方差位置与类型声明或参数的方差位置相反。

B的方差似乎没有涉及,但通常上限必须是协变的:

trait C[-A, B <: A] // contravariant type A occurs in covariant position

这必须以某种方式产生问题?但我无法想出一个证明这种结构在特定情况下变得不健全的例子......


至于组合功能,为什么不只是

class Composite[-A, B, +C](g: A => B, h: B => C) extends (A => C) {
  def apply(a: A) = h(g(a))
}

编辑:例如:

import collection.LinearSeq

def compose[A](g: Traversable[A] => IndexedSeq[A], h: Traversable[A] => LinearSeq[A]) =
  new Composite(g, h)