Che cosa significa l'operatore `#` in Scala?


131

Vedo questo codice in questo blog: Programmazione a livello di tipo 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]
}

C'è un operatore #nel codice R#X[R#Next]che non ho mai visto. Dal momento che è difficile cercarlo (ignorato dai motori di ricerca), chi può dirmi cosa significa?


1
il "cancelletto" viene talvolta definito "ottatrop" (quella ricerca su google mi ha portato a questa pagina).
Philwalk,


A proposito di altri operatori come # + e # - (vedi github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/… )? C'è un elenco completo?
Markus Barthlen,

Risposte:


240

Per spiegarlo, dobbiamo prima spiegare le classi nidificate in Scala. Considera questo semplice esempio:

class A {
  class B

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

Ora proviamo qualcosa con esso:

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)
                   ^

Quando dichiari una classe all'interno di un'altra classe in Scala, stai dicendo che ogni istanza di quella classe ha una tale sottoclasse. In altre parole, non esiste una A.Bclasse, ma ci sono a1.Be a2.Bclassi e sono classi diverse , come ci dice il messaggio di errore sopra.

Se non lo capisci, cerca i tipi dipendenti dal percorso.

Ora, #ti consente di fare riferimento a tali classi nidificate senza limitarlo a una particolare istanza. In altre parole, non c'è A.B, ma c'è A#B, il che significa una Bclasse nidificata di qualsiasi istanza di A.

Possiamo vederlo al lavoro modificando il codice sopra:

class A {
  class B

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

E provandolo:

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.

Ottimo esempio Accetto totalmente che funzioni in questo modo ma difficile da capire: scala> classOf [A # B] res7: Class [A # B] = class A $ B scala> classOf [aB] res8: Class [aB] = class A $ B. il che significa che in realtà hanno lo stesso tipo?
Chirone

2
I loro valori hanno la stessa rappresentazione di stringa e potrebbero anche essere uguali. Classè una rappresentazione runtime delle classi Java ed è limitata anche in Java. Ad esempio, List<String>e List<Integer>hanno lo stesso runtime Class. Se Classnon è abbastanza ricco per rappresentare i tipi Java , è quasi inutile quando si rappresentano i tipi di Scala . Ancora una volta, a res7: Class[A#B] = class A$Bsinistra del segno uguale è un tipo, a destra del tipo uguale se un valore che è la rappresentazione runtime Java di una classe.
Daniel C. Sobral,

13

È noto come proiezione del tipo e viene utilizzato per accedere ai membri del tipo.

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

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

6
Questa è una non risposta. In pratica mostra lo stesso codice della domanda, leggermente abbreviato. Qual è, ad esempio, la differenza per indicare la notazione? Dove dovrei usare questo # in codice reale?
notan3xit,

2
@ notan3xit forse è una non risposta a ciò che intendevi chiedere. Ma quello che mi hai chiesto è "... che non ho mai visto. Dato che è difficile cercarlo (ignorato dai motori di ricerca), chi può dirmi cosa significa?"
nafg


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.