How to enter-annotate this HList?

sealed abstract trait HList case class :+:[H, T <: HList](head: H, tail: T) extends HList { def :+:[T](v: T) = new :+:(v, this) } case object HNil extends HList { def :+:[T](v: T) = new :+:(v, this) } object HListExpt { def main(args: Array[String]) { val me: String :+: Int :+: Symbol :+: HNil.type = "Rahul" :+: 20 :+: 'Male :+: HNil println(me.head, me.tail.head) } } 

When I try to compile the above code, I get the following compiler error:

 error: type mismatch; found : :+:[java.lang.String,:+:[Int,:+:[Symbol,object HNil]]] required: :+:[String,:+:[Int,:+:[Symbol,HNil.type]]] val me: String :+: Int :+: Symbol :+: HNil.type = "Rahul" :+: 20 :+: 'Male :+: HNil 

What am I doing wrong here? What will be the correct type of input annotation above HList ?

PS: the code compiles fine when I remove the type annotation.

+4
scala hlist
source share
2 answers

The root problem is that singleton types are never inferred. Here is a demo:

 scala> case object A defined module A scala> A res6: A.type = A scala> identity[A.type](A) res7: A.type = A scala> identity(A) res8: object A = A 

Why is this? Quoth Odersky et. et al. in the Program in Scala, Β§27.6:

Typically, the [singleton] types are also useful, so the compiler does not want to insert them automatically.

So, let's explicitly specify an argument of type:

 sealed abstract trait HList case class :+:[H, T <: HList](head: H, tail: T) extends HList { def :+:[T](v: T) = new :+:(v, this) } case object HNil extends HList { def :+:[T](v: T) = new :+:[T, HNil.type](v, this) } val me: String :+: Int :+: Symbol :+: HNil.type = "Rahul" :+: 20 :+: 'Male :+: HNil println(me.head, me.tail.head) 

Bonus link:

+7
source share

I'm not sure why, but if HNil is defined as a class, everything compiles:

 class HNilClass extends HList { def :+:[T](v: T) = new :+:(v, this) } object HNil extends HNilClass 
+2
source share

All Articles