pego aquí la respuesta de Lars Hupel (así, todos los créditos se aplican a él), que en su mayoría se explica lo que quería saber:
Voy a darle una puñalada aquí. Creo que el uso de la función es claro cuando se habla de miembros de tipo.
Supongamos que usted tiene que poner en práctica los siguientes rasgos:
trait Function {
type Out[In]
def apply[In](x: In): Out[In]
}
Esta sería una función (genérico), donde el tipo de retorno depende de el tipo de entrada. Un ejemplo para una instancia:
val someify = new Function {
type Out[In] = Option[In] def
apply[In](x: In) = Some(x)
}
someify(3) res0: Some[Int] = Some(3)
Hasta ahora, todo bien. Ahora, ¿cómo definirías una función constante?
val const0 = new Function {
type Out[In] = Int
def apply[In](x: In) = 0
}
const0(3) res1: const0.Out[Int] = 0
(El tipo const0.Out[Int]
es equivalente a Int
, pero no es impresa de esa manera.)
Nota cómo no se utiliza realmente el parámetro de tipo In
. Por lo tanto, aquí es cómo se podría escribir con _
:
val const0 = new Function {
type Out[_] = Int
def apply[In](x: In) = 0
}
Piense en _
en ese caso como un nombre para el parámetro de tipo que realidad no se puede hacer referencia a.Es una para una función en el nivel de tipo que no se preocupan por el parámetro, al igual que en el nivel de valor :
(_: Int) => 3 res4: Int => Int = <function1>
Excepto ...
type Foo[_, _] = Int
<console>:7: error: _ is already defined as type _
type Foo[_, _] = Int
compararlo con:
(_: Int, _: String) => 3 res6: (Int, String) => Int = <function2>
Por lo tanto, en conclusión:
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)
Lo principal que mencionó, class A[_]
, es completamente simétrico al que, excepto que no existe un caso de uso real.
Considera:
trait FlyingDog[F[_]] { def swoosh[A, B](f: A => B, a: F[A]): F[B] }
Ahora supuesto de que desea hacer una instancia de FlyingDog
para su llanura de edad class A
.
hay dos soluciones:
Declarar class A[_]
lugar. (No haga eso.)
utilizar un tipo lambda:
new FlyingDog[({ type λ[α] = A })#λ]
o incluso
new FlyingDog[({ type λ[_] = A })#λ]
Lo que quiere decir aquí es un tipo existencial, que no es Lo que quise decir. – sschaef