Looking at the sources for shapeless library, i've paid attention to different higher-kinded type member declaration and wondering if it has some concrete difference in usage. For example generic trait here:
trait Generic1[F[_], FR[_[_]]] {
type R[t]
// ...
}
trait IsHCons1[L[_], FH[_[_]], FT[_[_]]] {
type H[_]
// ...
}
One type member is declared with a common syntax for type constructors (i.e H[_]
) and Generic1
trait has R[t]
. Though auxiliary type aliases are defined in a similar fashion:
object Generic1 {
type Aux[F[_], FR[_[_]], R0[_]] = Generic1[F, FR] { type R[t] = R0[t] }
// ...
}
object IsHCons1 {
type Aux[L[_], FH[_[_]], FT[_[_]], H0[_], T0[_] <: HList] = IsHCons1[L, FH, FT] { type H[t] = H0[t] ; type T[t] = T0[t] }
// ...
}
So i wonder if R[t]
and H[_]
has any difference or not?
There is no difference, as t
is just unbound. You can easily verify this in the REPL:
scala> type T1 = { type R[t] }
defined type alias T1
scala> type T2 = { type R[_] }
defined type alias T2
scala> implicitly[T1 =:= T2]
res0: =:=[T1,T2] = <function1>
The fact that the last line compiles proves that the compiler sees T1
and T2
as the same type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With