Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between higher-kinded type members declaration

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?

like image 635
4lex1v Avatar asked Aug 11 '15 09:08

4lex1v


Video Answer


1 Answers

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.

like image 100
Régis Jean-Gilles Avatar answered Sep 29 '22 23:09

Régis Jean-Gilles