4 Stimmen

Wie kann man diese HL-Liste korrekt abtippen?

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)
  }
}

Beim Versuch, den obigen Code zu kompilieren, erhalte ich den folgenden Compilerfehler:

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

Was mache ich hier falsch? Was wäre der korrekte Weg, um die obigen Angaben zu notieren? HList ?

PS: Der Code lässt sich gut kompilieren, wenn ich die Typ-Anmerkung entferne.

7voto

retronym Punkte 54220

Das Wurzelproblem ist, dass Singleton-Typen niemals abgeleitet werden. Hier ist eine Demonstration:

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

Warum ist das so? Zitat Odersky et. al. in Programming in Scala, §27.6:

Normalerweise sind [Singleton]-Typen zu spezifisch, um nützlich zu sein, weshalb der Compiler zögert, eine sie automatisch einzufügen.

Geben wir also explizit das Typ-Argument an:

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:

2voto

Ich bin mir nicht sicher, warum, aber wenn HNil als Klasse definiert ist, lässt sich alles kompilieren:

class HNilClass extends HList {
  def :+:[T](v: T) = new :+:(v, this)
}

object HNil extends HNilClass

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X