首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >逆方差和值

逆方差和值
EN

Stack Overflow用户
提问于 2011-02-24 06:24:34
回答 4查看 498关注 0票数 2

为什么'val‘和'case’会影响类型系统?(特别是方差)

代码语言:javascript
复制
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class E[-A]
defined class E

scala> class F[-A](val f: E[A] => Unit)
<console>:6: error: contravariant type A occurs in covariant position in type => (E[A]) => Unit of value f
class F[-A](val f: E[A] => Unit)
                       ^  
scala> case class C[-A](f: E[A] => Unit)
<console>:6: error: contravariant type A occurs in covariant position in type => (E[A]) => Unit of value f
   case class C[-A](f: E[A] => Unit)

scala> class F[-A](f: E[A] => Unit)    
defined class F
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-02-24 08:39:57

请考虑以下内容:

代码语言:javascript
复制
trait Equal[-A] { def eq(a1: A, a2: A): Boolean }
val e = new Equal[Option[Int]] { 
    def eq(a1: Option[Int], a2: Option[Int]) = a1 forall (x => a2 forall (x ==)) 
}

// Because Equal is contra-variant, Equal[AnyRef] is a subtype of Equal[String]
// Because T => R is contra-variant in T, Equal[AnyRef] => Unit is a supertype
// of Equal[String] => Unit
// So the follow assignment is valid
val f: Equal[AnyRef] => Unit = (e1: Equal[String]) => println(e1.eq("abc", "def"))


// f(e) doesn't compile because of contra-variance
// as Equal[Option[Int]] is not a subtype of Equal[AnyRef]

// Now let's tell Scala we know what we are doing
class F[-A](val f: Equal[A @uncheckedVariance] => Unit)

// And then let's prove we are not:
// Because F is contra-variant, F[Option[Int]] is a subtype of F[AnyRef]
val g: F[Option[Int]] = new F(f)

// And since g.f is Equal[Option[Int]] => Unit, we can pass e to it.
g.f(e) // compiles, throws exception

如果fF之外不可见,则不会发生此问题。

票数 4
EN

Stack Overflow用户

发布于 2011-02-24 07:24:43

你是在问方差是什么吗?如果你知道方差是什么,这是不言而喻的。没有"val“或"case”的示例没有涉及A的外部可见成员,因此它不会引起方差错误。

票数 2
EN

Stack Overflow用户

发布于 2011-02-24 08:40:28

'val‘表示该字段是外部可见的。考虑一下:

代码语言:javascript
复制
val f: E[Any] => Unit = { ... }
val broken: F[Int] = new F[Any](f) // allowed by -A annotation
val f2: E[Int] => Unit = broken.f // must work (types match)
val f3: E[Int] => Unit = f // type error

基本上,我们设法不安全地强制转换f,而没有显式地为它执行操作。只有当f可见时才有效,即如果您将其定义为val或使用case类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5097984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档