2013-06-04 88 views
5

我想更好地了解以下行为:斯卡拉类型限制和方差

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 

我可以看到,有可能是从问题边界变量和有界变量是相反的,尽管我不清楚具体问题是什么。 我更不清楚为什么改变绑定到视图边界的类型使事情好起来。在没有适用的隐式转换的情况下,我认为这两个定义在很大程度上具有相同的效果。如果有什么,我会期待一个观点必然会提供更多的恶作剧机会。

对于位I定义是在像函数的一些方法类的背景,我想这样做

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] 

实际上是可取的,但我仍然会喜欢更好地理解这里发生了什么。

+0

耐人寻味的......我花了100小时去找一个例子类型与类型绑定的安全性中断。没有发现:( – gzm0

+0

)另外,如果有一个例子对于绑定的类型是不合适的,很难看出如何在视图边界中进行替换来修复它。 –

+0

是的,我有点同意,但根本的区别在于视图边界总是根据类创建的类型进行转换,而这对于类型绑定来说并不一定是这种情况(说我的直觉至少......) – gzm0

回答

4

首先容易之一:

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

这相当于

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

由于view没有公开返回,它不是在这会限制的AB方差的位置。例如。

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

换句话说,C[-A, +B <% A]是没有什么不同C[-A, +B]在约束方面,视图参数不改变任何东西。


上界情况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) 
+0

有趣的是,谢谢,我没有想到要试试'特质C [-A,B <:A]'。我只是认为它必须是相反的差异。 –

+0

是的,它们组成,正是因为'Function1'的差异' –

+0

class'CompositeFunc [-A,B,+ C]'尽管它们的组合在两个指令中都是完全合理的,但它们不允许你使用'g:BaseFunc(Traversable [A],LinearSeq [A])'编写'f:BaseFunc(Traversable [A],IndexedSeq [A])' –