Skip to content

Instantly share code, notes, and snippets.

@TrustNoOne
Created April 29, 2016 11:48
Show Gist options
  • Save TrustNoOne/371b423ff3f5ba240774c9ea5d643e3f to your computer and use it in GitHub Desktop.
Save TrustNoOne/371b423ff3f5ba240774c9ea5d643e3f to your computer and use it in GitHub Desktop.
Higher Kinded type declarations in scala
trait Y
trait T[X]
trait TSub[X <: Y] extends T[X] // bounded
trait TCo[+X]
trait TCoSub[+X <: Y] extends TCo[X] // bounded
trait TContra[-X]
trait TContraSub[-X <: Y] extends TContra[X] // bounded
def m1[T0[_] <: T[_]] = ???
m1[T]
// m1[TSub] -> not accepted because of stricter bounds
def m1Co[T0[_] <: TCo[_]] = ???
m1Co[TCo]
// m1Co[TCoSub] -> not accepted because of stricter bounds
def m1Contra[T0[_] <: TContra[_]] = ???
m1Contra[TContra]
// m1Contra[TContraSub] -> not accepted because of stricter bounds
def m2[T0[A0] <: T[A0]] = ???
m2[T]
// m2[TSub] -> not accepted because of stricter bounds
def m2Co[T0[A0] <: TCo[A0]] = ???
m2Co[TCo]
// m2Co[TCoSub] -> not accepted because of stricter bounds
def m2Contra[T0[A0] <: T[A0]] = ???
// m2Contra[TContra] -> contravariant type is not accepted because for any A0 T0[A0] >: T[A0] instead of <:
// m2Contra[TContraSub] -> not accepted because of stricter bounds
def m3[A, T0[_] <: T[A]] = ???
// m3[Y, T] -> doesn't conform, T0[X] should be a subtype of T[Y] for every X.
// m3[Y, TSub] -> not accepted because of stricter bounds
def m3Co[A, T0[_] <: TCo[A]] = ???
// m3Co[Y, TCo] -> doesn't conform, T0[X] should be a subtype of TCo[Y] for every X.
// m3Co[Y, TCoSub] -> not accepted because of stricter bounds
def m3Contra[A, T0[_] <: TContra[A]] = ???
// m3Contra[Y, TContra] -> doesn't conform, T0[X] should be a subtype of TContra[Y] for every X.
// m3Contra[Y, TContraSub]-> not accepted because of stricter bounds
def m4[A, T0[_ <: A] <: T[_]] = ???
m4[Y, T] // Ok, wider bound
m4[Y, TSub] // Ok, wider bound
def m4Co[A, T0[_ <: A] <: TCo[_]] = ???
m4Co[Y, TCo] // Ok, wider bound
m4Co[Y, TCoSub] // Ok, wider bound
def m4Contra[A, T0[_ <: A] <: TContra[_]] = ???
m4Contra[Y, TContra] // Ok, wider bound
m4Contra[Y, TContraSub] // Ok, wider bound
def m5[A, T0[_ <: A] <: T[A]] = ???
// m5[Y, T] -> Wider bound but doesn't conform: T0[X <: Y] should be a subtype of T[Y] for every X but T0 is invariant
// m5[Y, TSub] -> Same bound but doesn't conform: T0[X <: Y] should be a subtype of T[Y] for every X but T0 is invariant
def m5Co[A, T0[_ <: A] <: TCo[A]] = ???
// m5Co[Y, TCo] -> doesn't conform: T0[X] should be a subtype of Tco[Y] for every X but T0 bound is larger
m5Co[Y, TCoSub] // Same bound/conforms because being T covariant T0[X] is a subtype of Tco[Y] for every X because X is bounded <: Y
def m5Contra[A, T0[_ <: A] <: TContra[A]] = ???
// m5Contra[Y, TContra] -> Wider bound but doesn't conform: T0[X] should be a subtype of T[Y] for every X, but X is contravariant
// m5Contra[Y, TContraSub] -> Same bound but doesn't conform: T0[X] should be a subtype of T[Y] for every X, but X is contravariant
def m6[A, T0[A0 <: A] <: T[A0]] = ???
m6[Y, T] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
m6[Y, TSub] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
def m6Co[A, T0[A0 <: A] <: TCo[A0]] = ???
m6Co[Y, TCo] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
m6Co[Y, TCoSub] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
def m6Contra[A, T0[A0 <: A] <: TContra[A0]] = ???
m6Contra[Y, TContra] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
m6Contra[Y, TContraSub] // bound ok, conforms because T0[X <: Y] is a subclass of T0[X] for every X (it's actually the same)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment