【问题标题】:Difference between def m(p: T forSome {type T} and def m1(p:Any), is there any ? Explanation needed based on Scala Language Specificationdef m(p: T forSome {type T} 和 def m1(p:Any) 有什么区别吗?需要根据 Scala 语言规范进行解释
【发布时间】:2015-02-27 10:23:33
【问题描述】:
object ExistentialTypesAsFunctionParameters extends App{

      def m(p: T forSome {type T})=p.toString
      def m1(p:Any)=p.toString
      println(m("Hello"))
      println(m1("Hello"))
}

此程序运行并打印Hello 两次。

mm1 有什么区别,有什么区别吗?

Any 相比,存在类型T forSome {type T} 允许的值是多少?

最重要的是

如何根据 Scala 语言规范回答这些问题?

换句话说,需要根据 Scala 语言规范进行解释。

编辑:

跟进问题:

class Top
class Middle extends Top {override def toString()="Middle"}
class Bottom extends Middle
object ExistentialTypesAsFunctionParameters extends App{    
  def m3(p: T forSome {type T >: Middle })=p.toString
  println(m3(new Middle))
  println(m3(new Bottom))
  println(m3(new Top))
}

此代码编译并运行。

但我希望println(m3(new Bottom)) 不会编译,因为T forSome {type T >: Middle } 的限制应该意味着任何类型可以是Middle 子类型的值v 不应该具有T forSome {type T >: Middle } 类型。

那么为什么这段代码还能编译呢?

【问题讨论】:

    标签: scala types existential-type


    【解决方案1】:

    根据 SLS 第 6.1 节,p.toString 中的表达式 p 的类型是 T forSome {type T} 的 skolemization:

    以下 skolemization 规则普遍适用于每个 表达式:如果表达式的类型是存在类型 T ,则表达式的类型被假定为 T 的 skolemization (§3.2.10)。

    我们可以看到 Any 遵循您报价中的 skolemization 规则。

    所以当用作表达式的类型时T forSome {type T}Any 具有相同的效果,并且它会接受相同的可能值。并且当用作类型时,如果它的 skolemization 确实(根据 3.5.2),它将被认为符合给定类型。但是这些类型等同于第 3.5.1 节中定义的。也就是说,即使在类型级别上,我也看不出有任何方法可以区分它们。

    编辑:T forSome {type T >: Middle} 只是Middle 的任何超类型,即Any 再次符合这一点。 Any >: Middle 所以Any <: T forSome {type T >: Middle}Bottom <: Any,所以Bottom 仍然可以通过。如果您想防止传递特定类型的子类型,您可以使用这些子类型不存在的类型类(通过故意为这些子类型创建隐式解决冲突)。

    【讨论】:

    • 能否请您对编辑中的后续问题发表评论?
    • 感谢您对后续问题的评论,这是非常有帮助的解释。
    猜你喜欢
    • 2020-03-27
    • 2017-05-15
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2016-06-14
    • 2010-11-05
    • 2011-03-25
    • 1970-01-01
    相关资源
    最近更新 更多