2012-02-25 138 views
94

我看到这个代码在这个博客:Type-Level Programming in Scala`#`运算符在Scala中的含义是什么?

// define the abstract types and bounds 
trait Recurse { 
    type Next <: Recurse 
    // this is the recursive function definition 
    type X[R <: Recurse] <: Int 
} 
// implementation 
trait RecurseA extends Recurse { 
    type Next = RecurseA 
    // this is the implementation 
    type X[R <: Recurse] = R#X[R#Next] 
} 
object Recurse { 
    // infinite loop 
    type C = RecurseA#X[RecurseA] 
} 

有中,我从来没有见过的代码R#X[R#Next]操作#。由于很难搜索它(被搜索引擎忽略),谁能告诉我这是什么意思?

+0

“英镑符号”有时被称为“八字符”(谷歌搜索带我到这个页面)。 – philwalk 2016-01-01 19:44:10

+2

使[octothorpe或octothorp](https://en.wikipedia.org/wiki/Number_sign) – smparkes 2016-03-13 23:09:53

+0

Whatabout其他运算符,如#+和# - (请参阅https://github.com/tpolecat/doobie/blob/series /0.4.x/yax/h2/src/main/scala/doobie/h2/H2Transactor.scala)?有全面的清单吗? – 2017-02-05 06:53:21

回答

184

来解释它,我们首先必须在斯卡拉解释嵌套类。考虑一个简单的例子:

class A { 
    class B 

    def f(b: B) = println("Got my B!") 
} 

现在,让我们尝试一些与它:

scala> val a1 = new A 
a1: A = [email protected] 

scala> val a2 = new A 
a2: A = [email protected] 

scala> a2.f(new a1.B) 
<console>:11: error: type mismatch; 
found : a1.B 
required: a2.B 
       a2.f(new a1.B) 
       ^

当你声明Scala的另一个类中的一类,你是说该类的每个实例有这样一个子类。换句话说,没有A.B类,但有a1.Ba2.B类,它们是不同的类,如上面的错误消息告诉我们的那样。

如果您不明白,请查找路径相关类型。

现在,#可以让您引用这样的嵌套类,而不会将其限制为特定的实例。换句话说,没有A.B,但有A#B,这意味着B嵌套类任何A的实例。

我们可以通过改变上面的代码工作中看到这一点:

class A { 
    class B 

    def f(b: B) = println("Got my B!") 
    def g(b: A#B) = println("Got a B.") 
} 

,并试图出来:

scala> val a1 = new A 
a1: A = [email protected] 

scala> val a2 = new A 
a2: A = [email protected] 

scala> a2.f(new a1.B) 
<console>:11: error: type mismatch; 
found : a1.B 
required: a2.B 
       a2.f(new a1.B) 
       ^

scala> a2.g(new a1.B) 
Got a B. 
+0

极好的例子。我完全接受,它的工作原理是这样,但很难理解这一点: 斯卡拉> classOf [A#B] res7:类[A#B] = A类$ B 斯卡拉> classOf [AB] res8 :Class [aB] = class A $ B 。这意味着,他们实际上具有相同的类型? – Chiron 2016-01-13 01:28:54

+2

它们的值具有相同的字符串表示 - 它们甚至可能相等。 'Class'是Java类的运行时表示,甚至在Java中也是有限的。例如,'List '和'List '具有相同的运行时类'Class'。如果'Class'不足以表示_Java_类型,则表示_Scala_类型时几乎没有用处。同样,'res7:Class [A#B] = class A $ B',等号左边的是一个类型,如果是类的Java _runtime_表示的值,则为equals类型的右边。 – 2016-01-21 00:16:57

8

它被称为类型投影,用于访问类型成员。

scala> trait R { 
    | type A = Int 
    | } 
defined trait R 

scala> val x = null.asInstanceOf[R#A] 
x: Int = 0 
+4

这是一个无法回答的问题。它基本上显示与问题相同的代码,只是略微缩短。例如,什么是点符号的区别?我在哪里可以使用这个#在真正的代码? – notan3xit 2012-02-25 12:33:53

+1

@ notan3xit也许这是一个无法回答你的意思要问。但是你所问的是“......我从未见过,因为很难搜索它(被搜索引擎忽略),谁能告诉我这是什么意思?” – nafg 2014-09-15 02:25:17