什么情况下空的HList不是HList?

4

在学习Shapeless时,我想知道为什么这段代码无法编译:

def someHList[H <: HList]: H = HNil

由于HNil对象扩展了HNil特征,而HNil特征扩展了HList,因此这是正确的。

在特征中定义一种方法的正确方式是仅由扩展类实现返回某些HList的方法。

我想做如下操作:

trait Parent {
  def someHList[H <: HList]: H
}

object Child1 extends Parent {
  def someHList[H <: HList] = HNil
}

object Child2 extends Parent {
  def someHList[H <: HList] = 1 :: "two" :: HNil
}

任何建议都会受到赞赏。谢谢!

编辑

为了阐明我在原问题中未明确的问题:

1.) 最好不需要在每个实现类中显式指定H,而是让它被推断出来(在调用站点?)。

2.) 我想在父特征中使用HNil作为默认实现,可以在子类中选择性地覆盖。我的例子可能应该是:

trait Parent {
  def someHList[H <: HList]: H = HNil
}

object Child extends Parent {
  override def someHList[H <: HList] = 1 :: "two" :: HNill
}

这个问题的标题是一个糟糕的双关语/参考,与这个经典的语言谜题在结构上相似:https://en.wikipedia.org/wiki/When_a_white_horse_is_not_a_horse - Ryan
2个回答

8
"HNil对象是一个HList。但它不一定是H。"
"

类似于定义:

"
def someHList[H <: HList]: H = HNil

应该理解为

对于任何类型 H,它是HList的子类型,都有一种方法来构造它的成员,并且它将是HNil

这显然是错误的

你试图做的事情,我感觉是重新表述它为:

存在一个类型 H,它是HList的子类型,并且存在一种方法来构造它的成员

如果是这样,你可以使用类型成员,如下所示:

import shapeless._

trait Parent {
  type H <: HList
  def someHList: H
}

object Child1 extends Parent {
  type H = HNil
  def someHList: H = HNil
}

object Child2 extends Parent {
  type H = Int :: String :: HNil
  def someHList: H = 1 :: "two" :: HNil
}

更新

您还可以对其进行一些重构,使某些类型自动推断,例如:

abstract class Parent[H <: HList](val someList: H)
object Child1 extends Parent(HNil: HNil)
object Child2 extends Parent(1 :: "two" :: HNil)

你可能会注意到,HNil的类型是手动设置的,这是因为object HNil的类型是HNilHNil.type子类型,有时可能会误导编译器

有道理,肯定是我问题的答案。现在我意识到我在问题中漏掉了一点:是否有一种方法可以在调用位置推断 H,而不必在每个实现类中显式指定它? - Ryan
谢谢!并且+1强调需要显式指定类型HNil: HNil - Ryan

4
如果只使用HList作为返回类型,那么一切都能正常工作:
trait Parent {
  def someHList: HList
}

object Child1 extends Parent {
  def someHList = HNil
}

object Child2 extends Parent {
  def someHList = 1 :: "two" :: HNil
}

或者针对问题的最新版本:

trait Parent {
  def someHList: HList = HNil
}

object Child2 extends Parent {
  override def someHList = 1 :: "two" :: HNil
}

这是一个很好的观点,但是没有任何类型参数或类型成员,这种不变式风格(据我所知)不能成为使用Aux模式构建的引理的一部分:https://github.com/underscoreio/shapeless-guide/blob/c4ecb5620b269d8080892eb69a85a9cc78d9778f/src/pages/ops/penultimate.md - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接