incollo qui la risposta da Lars Hupel (così, tutti i crediti si applicano a lui), il che spiega in gran parte quello che volevo sapere:
ho intenzione di dare una pugnalata qui. Penso che l'uso della funzione rimuova quando si parla di membri di tipo.
supponga che è necessario implementare la seguente caratteristica:
trait Function {
type Out[In]
def apply[In](x: In): Out[In]
}
Questa sarebbe una funzione (generica), dove il tipo di ritorno dipende il tipo di ingresso. Un esempio per un'istanza:
val someify = new Function {
type Out[In] = Option[In] def
apply[In](x: In) = Some(x)
}
someify(3) res0: Some[Int] = Some(3)
Finora, tutto bene. Ora, come definiresti una funzione costante?
val const0 = new Function {
type Out[In] = Int
def apply[In](x: In) = 0
}
const0(3) res1: const0.Out[Int] = 0
(Il tipo const0.Out[Int]
è equivalente a Int
, ma non è stampate in questo modo.)
noti come il parametro di tipo In
non viene effettivamente utilizzato. Quindi, ecco come si potrebbe scrivere con _
:
val const0 = new Function {
type Out[_] = Int
def apply[In](x: In) = 0
}
Pensate _
in questo caso come un nome per il parametro tipo che non può in realtà essere indicato.E 'una per una funzione sul livello di tipo, che non si preoccupa del parametro, proprio come sul valore livello:
(_: Int) => 3 res4: Int => Int = <function1>
Tranne ...
type Foo[_, _] = Int
<console>:7: error: _ is already defined as type _
type Foo[_, _] = Int
Confronti che, con:
(_: Int, _: String) => 3 res6: (Int, String) => Int = <function2>
Quindi, in conclusione:
type F[_] = ConstType // when you have to implement a type member def
foo[_](...) // when you have to implement a generic method but don't
// actually refer to the type parameter (occurs very rarely)
La cosa principale che hai menzionato, class A[_]
, è completamente simmetrica a che, tranne che non esiste un vero caso d'uso.
Considerate questo:
trait FlyingDog[F[_]] { def swoosh[A, B](f: A => B, a: F[A]): F[B] }
Ora supporre si vuole fare un'istanza di FlyingDog
per la pianura vecchio class A
.
ci sono due soluzioni:
Declare class A[_]
invece. (Non farlo.)
utilizzare un tipo lambda:
new FlyingDog[({ type λ[α] = A })#λ]
o anche
new FlyingDog[({ type λ[_] = A })#λ]
cosa si intende qui è un tipo esistenziale, che non è cosa intendevo. – sschaef