148

I see this code in this blog: Type-Level Programming in 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]
}

There is an operator # in the code R#X[R#Next] which I've never seen. Since it's difficult to search it(ignored by search engines), who can tell me what does it mean?

Freewind
  • 193,756
  • 157
  • 432
  • 708
  • 1
    the "pound sign" is sometimes referred to as "octathrop" (that google search brought me to this page). – philwalk Jan 01 '16 at 19:44
  • 3
    Make that [octothorpe or octothorp](https://en.wikipedia.org/wiki/Number_sign) – smparkes Mar 13 '16 at 23:09
  • Whatabout other operators like #+ and #- (see https://github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/scala/doobie/h2/H2Transactor.scala)? Is there a comprehensive list? – Markus Barthlen Feb 05 '17 at 06:53

4 Answers4

269

To explain it, we first have to explain nested classes in Scala. Consider this simple example:

class A {
  class B

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

Now let's try something with it:

scala> val a1 = new A
a1: A = A@2fa8ecf4

scala> val a2 = new A
a2: A = A@4bed4c8

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

When you declare a class inside another class in Scala, you are saying that each instance of that class has such a subclass. In other words, there's no A.B class, but there are a1.B and a2.B classes, and they are different classes, as the error message is telling us above.

If you did not understand that, look up path dependent types.

Now, # makes it possible for you to refer to such nested classes without restricting it to a particular instance. In other words, there's no A.B, but there's A#B, which means a B nested class of any instance of A.

We can see this in work by changing the code above:

class A {
  class B

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

And trying it out:

scala> val a1 = new A
a1: A = A@1497b7b1

scala> val a2 = new A
a2: A = A@2607c28c

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.
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Excellent example. I totally accept that it works that way but hard to understand this: scala> classOf[A#B] res7: Class[A#B] = class A$B scala> classOf[a.B] res8: Class[a.B] = class A$B . which means, they have the same type actually? – Chiron Jan 13 '16 at 01:28
  • 3
    Their values have the same string representation -- and they might even be equal. `Class` is a runtime representation of Java classes, and it's limited even in Java. For example, `List` and `List` have the same runtime `Class`. If `Class` is not rich enough to represent _Java_ types, it's almost useless when representing _Scala_ types. Again, `res7: Class[A#B] = class A$B`, left of the equals sign is a type, right of the equals type if a value which is the Java _runtime_ representation of a class. – Daniel C. Sobral Jan 21 '16 at 00:16
17

It's known as type projection, and is used to access type members.

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

scala> val x = null.asInstanceOf[R#A]
x: Int = 0
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • 7
    This is a non-answer. It basically shows the same code as the question, just slightly shortened. What is, for example the difference to point notation? Where would I use this # in real code? – notan3xit Feb 25 '12 at 12:33
  • 4
    @notan3xit maybe it's a non-answer to what you meant to ask. But what you asked is "... which I've never seen. Since it's difficult to search it(ignored by search engines), who can tell me what does it mean?" – nafg Sep 15 '14 at 02:25
8

Basically, it's a way of referring to classes within other classes.

http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (search for "pound")

moveaway00
  • 918
  • 1
  • 5
  • 13
2

Here's a resource for searching on "symbolic operators" (which are really methods), but I haven't figured out how to escape "#" to search on in scalex)

http://www.artima.com/pins1ed/book-index.html#indexanchor

Gene T
  • 5,156
  • 1
  • 24
  • 24