How do I create a constrained HList from a sequence?

I have a constructor that has the following signature:

class Event[DL <: HList](
  detailsIn: DL
)(implicit lbcr: LUBConstraint[DL, EventDetail[_]]) { ... 

      

In the companion object, I:

  def apply[DL <: HList](
    detailIn: String*
  )(implicit lbcr: LUBConstraint[DL, EventDetail[String]]) =
    new Event(
      if (detailIn.map(deet => EventDetail(deet)).toList.size == 1)
        detailIn.map(deet => EventDetail(deet)).toList.toHList[String :: HNil].get
      else throw new NotImplementedException()
    )(lbcr)

      

Admittedly, this application method can be cleaned up.

This leads to the following error, which I frankly lost on how to deal with this:

Error:(87, 7) type mismatch;
 found   : shapeless.LUBConstraint[DL,edu.cornell.ansci.dairy.econ.model.event.EventDetail[String]]
 required: shapeless.LUBConstraint[shapeless.::[String,shapeless.HNil],edu.cornell.ansci.dairy.econ.model.event.EventDetail[_]]

      

Second part of the problem: is there a way to make this polymorphism over detailIn size? Based on my other readings, I guess not, and I can't think of any way to do this in Scala. The best I can do is maintain, for convenience, the length of fixed numbers for the sequence of strings in the InIn sequence, and if this is exceeded, the user of the class must use the HList directly.

+3


source to share


1 answer


Don't be afraid of this type of error, it's pretty obvious, let me try to type the body of your method apply

from the bottom up:

At the very bottom, you have String :: HNil

:

val e0: String :: HNil = e.toList.toHList[String :: HNil].get

      

if

doesn't change this:

val e1: String :: HNil = 
  if (???) e0
  else throw new NotImplementedException()

      



Thus, when you create Event

, Event.DL = String :: HNil

:

new Event[String :: HNil](e1)(lbcr)

      

But it lbcr

has a type LUBConstraint[DL, _]

that is incompatible with LUBConstraint[String :: HNil, _]

!

For the second part of your question, shapeless provides a safer alternative to varargs: ProductArgs . With support for a macro and a slightly more complex definition object myfunction extends ProductArgs { def applyProduct[L <: HList](args: L) }

instead, def myfunction(args: Any*)

you can get your varargs like HList

instead Seq[String]

.

+2


source







All Articles