在斯卡拉type`的调查`和``#关键字(investigation of `type` and `

2019-08-01 14:59发布

可能有人解释如何type关键字和#操作符在Scala和如何使用它? 请看例子。

//Example1
scala>  type t1 = Option.type
defined type alias t1

//Shouldn't this work since previous example simply works?
scala>  type t2 = String.type
<console>:7: error: type mismatch;
 found   : String.type
 required: AnyRef
       type t2 = String.type
         ^

//lets define custom trait T
scala>  trait T
defined trait T

//... and obtain it's type like in Example1.
//Shouldn't this work since previous Example1 simply works?
scala>  type t3 = T.type
<console>:7: error: not found: value T
       type t3 = T.type
         ^

//Lets define some value of type T
scala>  val v4 = new T{}
v4: T = $anon$1@5c3e8c76

//and obtain it's type (works)
scala>  type t4 = v4.type
defined type alias t4

//this doesn't work
scala>  type t4_1 = (new T{}).type
<console>:1: error: identifier expected but 'new' found.
       type t4_1 = (new T{}).type

//as well as this (doesn't work)
scala>  type t5 = "abc".type
<console>:1: error: identifier expected but string literal found.
       type t5 = "abc".type
         ^

//but this compiles well
scala>  val v6 = "abc"
v6: String = abc

scala>  type t6 = v6.type
defined type alias t6


//lets create some values of created types:
scala>  type t1 = Option.type
defined type alias t1

scala>  val v1_1 = Some(10)
v1_1: Some[Int] = Some(10)

scala>  type t7 = v1_1.type
defined type alias t7

scala>  val v7:t7 = null
v7: t7 = null

scala>  val v7_1:t7 = v1_1
v7_1: t7 = Some(10)

scala>  val v7_2:t7 = Some(10)
<console>:9: error: type mismatch;
 found   : Some[Int]
 required: t7
    (which expands to)  v1_1.type
       val v7_2:t7 = Some(10)
             ^


//next let's try # operator

scala>  class X[A,B](a:A,b:B)
defined class X

//doesn't work
scala>  type xa = X[A,B]#A
<console>:8: error: not found: type A
       type xa = X[A,B]#A
           ^
<console>:8: error: not found: type B
       type xa = X[A,B]#A
             ^

//but such approach works:
scala>  trait X2[C]{
  type A
  type B
  val c:C
}
defined trait X2

scala>  type xa2_1 = X2[String]#A
defined type alias xa2_1

scala>  type xa2_2[M] = X2[M]#A
defined type alias xa2_2

Answer 1:

首先,你的问题,您type

类型声明的右侧必须是一个稳定的路径的类型的名称。 因此,采取一个你的例子之一:

type t1 = Option.type

T1是的类型的别名Option 对象 ,而不是Option类。

type t2 = String.type

这是一个错误,因为没有String对象。 该错误是一个有点古怪,因为字符串是一个Java类,因此在不同的规则下运行(因为Java类永远不会有同伴)。

type t3 = T.type

同上。 这一次错误的更清楚,因为T是斯卡拉类,因此编译器可以毫不含糊地说,“T不与类型名称的对象”

type t4 = v4.type

这是由VAL命名的对象的单类型v4 。 它不是指类型T,或者你创建的匿名类的甚至任何实例的任何实例new T{}表达。 它指的是由所表示的类型v4null ,即,它们是该类型的唯一的允许值。

type t4_1 = (new T{}).type

这是非法的,因为事情你正在做的类型必须是一个稳定的标识符(大致,一个标识符,其引用的资源永远无法改变-如果给idenfier的完整路径包括套餐,只有人名的object秒, val S,它的稳定)。

type t5 = "abc".type

同上。

type t6 = v6.type

v6是一个稳定的标识符。 t6是仅通过由所述名称为字符串的该特定实例居住的类型v6 (和null )。

type v6 = v1_1.type

再次,一个单型。

val v7: t7 = null

null的类型是有效的值t7

val v7_1:t7 = v1_1

因此,这是特定的对象。

val v7_2:t7 = Some(10)

但是,这是一个不同的对象(即使它==v7 ,它不eq的话),因此不在此类型的成员。

现在关于#

class X[A,B](a:A,b:B)

AB是类型参数。 他们不能在类外被引用。 你可以把它们像抽象类型别名与private[this]可见,虽然这并不完全准确。

type xa = X[A,B]#A

所以,是的,不可见的。

type xa2_1 = X2[String]#A

由于 A指公共类型别名,可以通过名称的类之外的引用。 请注意,这个特殊的情况下是很没用,因为你知道绝对没有任何有关此类型。 如果你的特质X2有一个返回类型的值的方法A ,你可以这样做

val aFromX2: xa2_1 = x2instance.methodThatReturnsAnA

..但那么你不能做任何事情有了它,即使它传递回的实例X2[String]因为没有保证,这两个A s就指的是同一类型的! 在另一方面,如果你有一个具体的例子,你可以这样做:

def passAroundA(x2instance: X2[String]) {
  type x2a = x2instance.A // note dot, not #
  val a: x2a = x2instance.methodThatReturnsAnA
  x2instance.methodThatTakesAnA(a)
}

在这种情况下,它的作品,因为即使我们不知道A实际上是,我们知道,这两种方法使用相同类型 -无论是固定在x2instance的建设。



Answer 2:

实际上对于你的问题一切都在说明这个恕我直言,是绝对必要的谈话像模式匹配等,我建议你花时间来观看它和努力,它的东西用例。 相关的东西很多斯卡拉类型的系统实际上是一个神奇的我,直到我看了这部影片。 我可能会放过我的很多人天试图解决系统类型怪异的行为和类型推断,如果我知道这些事情。



文章来源: investigation of `type` and `#` keywords in scala