HList filtered by foldRight is not providing instances

徘徊边缘 提交于 2019-12-06 09:31:56

问题


I'm using libraryDependencies += "com.chuusai" %% "shapeless" % "2.2.4"

Currently i have model HList types like

sealed trait Section
case class Header(...) extends Section
case class Customer(...) extends Section
case class Supplier(...) extends Section
case class Tech(...) extends Section
type ContractView = Header :: (Customer :: Supplier :: HNil) :: Tech :: HNil

In my user code, i'd like to filter technical sections that are not supposed to view using foldRight as proposed in this answer:

trait collectAllRF extends Poly2 {
  implicit def atAny[L <: HList, X] = at[X, L](_ :: _)
}

object collectVisRF extends collectAllRF {
  implicit def atInvis[L <: HList, S <: Section : InvisibleSection] = at[S, L]((_, l) => l)
}

For example there are defined:

trait InvisibleSection[S <: Section]
implicit object _techisInvisible extends InvisibleSection[Tech]

Fold is working correctly, but suddenly i could not use following filter or map on this object, so for example this code:

val filtered = view.foldRight(HNil)(collectVisRF)
view.filter[Header] 

produces compile error:

error: could not find implicit value for parameter partition: shapeless.ops.hlist.Partition[shapeless.::[Header,shapeless.::[shapeless.::[Customer,shapeless.::[Supplier,shapeless.HNil]],shapeless.HNil.type]],Header]

while this

view.filter[Header]

and this

val h = view.select[Header] 
val l = view.select[Customer::Supplier::HNil]
val c = l.select[Customer]
val s = l.select[Supplier]
val manual = h :: (c :: s :: HNil) :: HNil
manual.filter[Header]

compiles ok

Lately i've found little HNil.type at end of foldRight's result type and changed my filter definition to

view.foldRight(HNil.asInstanceOf[HNil])(collectVisRF)

And all worked properly

Is this an expected behaviour, and if yes why there is no some

val hNil: HNil = HNil

In the library?


回答1:


Your eventual fix is almost, but not quite, right. Rather than asInstanceOf you should use a type ascription,

view.foldRight(HNil: HNil)(collectVisRF)

Your question about why there is no definition of an hnil value typed as HNil rather than as HNil.type is a good one. shapeless is different from typical Scala libraries in that it makes heavy use of singleton types, HNil.type included, so the current situation isn't as obviously wrong as the corresponding situation in the Scala standard library where None.type and Nil.type are almost never desired.

Nevertheless the situation you describe in your question comes up more often than I would like, so it's clearly a real problem. I think it would be too confusing to have two hnil values, one with a more precise type than the other, so the question boils down to: how much existing stuff would break if HNil (the type) was inferred as the type of HNil (the value) rather than HNil.type as it is now.

Feel free to open a ticket in the shapeless issue tracker on Github to investigate this, and if you'd like to give it a try, please do :-)



来源:https://stackoverflow.com/questions/31583360/hlist-filtered-by-foldright-is-not-providing-instances

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!