def m(p:T forSome {type T}和def m1(p:Any)之间的区别是否有?基于Scala语言规范需要说明

时间:2014-12-31 09:48:36

标签: scala types existential-type

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之间有什么区别,有没有?

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

最重要的是

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

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

enter image description here

编辑:

跟进问题:

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 }应该意味着任何类型可以是v的子类型的值Middle都不应该类型T forSome {type T >: Middle }

那么为什么这段代码仍然可以编译?

1 个答案:

答案 0 :(得分:1)

pp.toString的表达式类型是T forSome {type T}的重新定义,符合SLS第6.1节:

  

以下的石油化规则适用于所有人   表达式:如果表达式的类型是存在类型   T,然后假设表达式的类型为a   t。

的skolemization(§3.2.10)

我们可以看到Any遵循你的引用中的skolemization规则。

因此当用作表达式的类型时,T forSome {type T}Any具有相同的效果,并且它将允许相同的可能值。当作为一种类型使用时,如果它的特征化,它将被认为符合给定的类型(根据3.5.2)。但是类型等同于3.5.1节中的定义。也就是说,即使在类型级别,我也看不出任何区分它们的方法。

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