【问题标题】:Shapeless HList return type无形 HList 返回类型
【发布时间】:2021-02-18 20:47:47
【问题描述】:

我试图在我的代码中加入一些无形的东西,但我遇到了一个令人尴尬的早期障碍。在下面的示例中,似乎 HCons 将未定义的对象添加到 HNil:

trait HasValue[A, B] {
  def get(a: A): B
  def getAll[L <: HList, O <: HList](a: A)(implicit ga: GetAll[A, L]): O = ga.getAll(a, HNil)
}

trait GetAll[A, B] {
  def getAll[L <: HList, O <: HList](a: A, l: L): O
}
implicit def getAllIfHasValue[A, B](implicit ev: HasValue[A, B]) = new GetAll[A, B] {
  def getAll[L <: HList, O <: HList](a: A, l: L): O = ev.get(a) :: l
}

并得到一个错误 - type mismatch: Found B :: L, Required O。 我会认为,因为L 本身就是HListB :: L 本身应该是HList,因此一切都应该很好。但显然不是。

任何帮助表示赞赏!

【问题讨论】:

  • 不清楚您要达到的目标。 getAll 签名看起来很可疑:它表示对于每个 HList 类型 LO,您可以仅基于 LA 生成 O。这个函数没有合理的实现(除了总是返回HNil)。也许您想将LO 移到特征类型参数列表中。
  • @simpadjo - 是的 - 我在这里没有使用一个很好的例子。在我正在阅读的示例中,有一点让我感到有些困惑,那就是人们倾向于使用 def f[L &lt;: HList]: L = 1 :: HNil 的语法(当使用 HLists 作为函数参数或返回类型时)。为什么这里需要L 类型参数对我来说并不是很明显。为什么不简单地def f: HList = 1 :: HNil
  • HList type 没有说明其元素的类型。 L 也应该携带有关元素的信息。
  • @Chrisper 顺便说一句,def f[L &lt;: HList]: L = 1 :: HNil 不正确。这就好像我写了def f[A]: A = 1。我想你应该想想 Scala 中的类型参数是什么意思。
  • @Chrisper 如果您写到1 :: HNil 的类型为HList,您将丢失有关Int :: HNil 的类型级别信息。 HList 并不比 List[Any] 好。

标签: scala generics typeclass implicit shapeless


【解决方案1】:

我猜这个错误很明显

type mismatch;
 found   : B :: L
 required: O

ev.get(a) :: l 的类型为 B :: L,但应为 O

我会认为,既然L 本身就是一个HList,那么B :: L 本身应该是一个HList,因此一切都应该很好。

B :: L 确实是HList。问题是B :: L 不是O

当你写签名时

def getAll[L <: HList, O <: HList](a: A, l: L): O = ???

这意味着,对于任何类型L &lt;: HList任何类型 O &lt;: HList,具有a: Al: L 的值都会产生O 类型的值。我猜这不是你想要的。

也许您想根据类型 AB 返回类型 O。然后可以引入类型参数

trait GetAll[A, B] {
  type O
  def getAll[L <: HList](a: A, l: L): O
}

或者您可能想要返回一个类型 O,具体取决于类型 ABL &lt;: HList。然后另外你应该将L转移到特征级别

trait GetAll[A, B, L <: HList] {
  type O
  def getAll(a: A, l: L): O
}

【讨论】:

  • 谢谢 - 是的,我想我一直对类型参数在这种情况下的工作方式有些困惑。我现在已经弄清楚了潜在的问题(我最初的例子是一个糟糕的代表)。
猜你喜欢
  • 1970-01-01
  • 2014-06-03
  • 2017-02-10
  • 1970-01-01
  • 2016-07-30
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多