3

我在用着libraryDependencies += "com.chuusai" %% "shapeless" % "2.2.4"

目前我有模型 HList 类型,如

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

在我的用户代码中,我想过滤不应该查看的技术部分,如本答案foldRight中建议的那样:

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

例如有定义:

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

折叠工作正常,但突然我无法在此对象上使用以下filtermap,例如此代码:

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

产生编译错误:

错误:找不到参数分区的隐式值:shapeless.ops.hlist.Partition[shapeless.::[Header,shapeless.::[shapeless.::[Customer,shapeless.::[Supplier,shapeless.HNil]] ,shapeless.HNil.type]],标题]

而这

view.filter[Header]

和这个

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]

编译正常

最近我在 's 结果类型HNil.type的末尾发现很少,foldRight并将我的过滤器定义更改为

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

一切正常

这是预期的行为吗,如果是,为什么没有一些

val hNil: HNil = HNil

在图书馆?

4

1 回答 1

4

您的最终修复几乎是正确的,但并不完全正确。而不是asInstanceOf你应该使用类型归属,

view.foldRight(HNil: HNil)(collectVisRF)

您关于为什么没有定义类型为 asHNil而不是 as的 hnil 值的问题HNil.type是一个很好的问题。shapeless 与典型的 Scala 库的不同之处在于它大量使用了单例类型,HNil.type包括在内,因此目前的情况并不像 Scala 标准库中的相应情况那样明显错误,None.type而且Nil.type几乎从不需要。

尽管如此,您在问题中描述的情况比我想的更频繁,所以这显然是一个真正的问题。我认为拥有两个 hnil 值会太令人困惑,一个比另一个具有更精确的类型,所以问题归结为:如果将HNil(类型)推断为HNil(值)的类型,现有的东西会破坏多少) 而不是HNil.type现在这样。

随意在 Github 上的 shapeless 问题跟踪器中打开一张票来调查这个问题,如果你想尝试一下,请这样做:-)

于 2015-07-23T10:17:07.423 回答