Hugo Corrêa
Hugo Corrêa

Reputation: 21

covariant type occurs in invariant position in HList

I am trying to define a type safe heterogeneous list which has restrictions on the types of its elements, enforcing an hierarchy between the elements (e.g type A cannot appear after type B). The trouble happens when attempting to convert my structure to shapeless' HList.

Below is how I define the traits for my type:

sealed trait Hierarchy {
  type HListType <: HList
  def toHList : HListType

  def toCaseClass[C](implicit gen: Generic[C]{type Repr >: HListType}) = gen.from(toHList)
}

sealed trait <::[+H <: ElType[_], +T <: Hierarchy] extends Hierarchy {

  override type HListType = H :: tail.HListType

  val head: H
  val tail: T

  override def toHList: HListType = head :: tail.toHList

}

I get the following error:

Hierarchy.scala:26: covariant type H occurs in invariant position in type shapeless.::[H,<::.this.tail.HListType] of type HListType

This is quite puzzling, since the definition of shapeless.:: defines that both type parameters are covariant.

I am using scala 2.11.11 and shapeless 2.3.2. Is there a way to fix this error?

Upvotes: 1

Views: 349

Answers (1)

Hugo Corr&#234;a
Hugo Corr&#234;a

Reputation: 21

From the Scala spec:

The right-hand side of a type alias is always in invariant position.

So the problem is not from the definition of HList, but from the fact that I'm using the type parameter in a type alias.

I changed the definition to

sealed trait <::[+H, +T <: Hierarchy] extends Hierarchy {

  type H_ <: ElType[H]

  override type HListType = H_ :: tail.HListType

  val head: H_
  val tail: T

  override def toHList: HListType = head :: tail.toHList

}

And the problem disappears.

Upvotes: 1

Related Questions