使用shapeless.Generic时,如何避免错误'super constructor cannot be passed a self reference unless parameter is declared by-name'?
When using shapeless.Generic, how to avoid the error 'super constructor cannot be passed a self reference unless parameter is declared by-name'?
下面的简单程序在现成的 scala 2.12 和 shapeless 2.3.2 下无法编译:
import shapeless.Generic
object InferGeneric {
class WithGeneric[T](implicit ev: Generic[T])
case class Impl() {}
object Impl extends WithGeneric[Impl]
}
编译器抛出以下错误:
/.../InferGeneric.scala:11: super constructor cannot be passed a self reference unless parameter is declared by-name
object Impl extends WithGeneric[Impl]
有趣的是,当 object Impl
重命名后,它可以毫无问题地编译。似乎通用推理中使用的宏在与伴随对象组合时会导致一些循环解析。如何避免这种情况?
非常感谢您的意见!
问题是宏生成的代码,但它并不是真正特定于宏的。您可以使用明确定义的实例重现该问题:
import shapeless._
class WithGeneric[T](implicit ev: Generic[T])
case class Impl()
object Impl extends WithGeneric[Impl]()(
new Generic[Impl] {
type Repr = HNil
def to(p: Impl): Repr = HNil
def from(p: Repr): Impl = Impl()
}
)
或者如果您想确保没有涉及宏:
trait Generic[A] { def mk: A }
class WithGeneric[T](ev: Generic[T])
case class Impl()
object Impl extends WithGeneric[Impl](
new Generic[Impl] { def mk: Impl = Impl() }
)
通常,在实例化 Impl
伴随对象时,您将无法在构造函数调用中传递调用 Impl.apply
的代码。
如果不进一步了解您要使用 WithGeneric
做什么,就很难提出解决方法。在像这样的简单情况下,您可以显式定义 Generic[Impl]
并仅使用 new Impl
构造函数(而不是 Impl.apply
)。如果您想要的是能够提供具有抽象大小写定义的伴随对象便捷方法 类,您可以这样做:
import shapeless._
abstract class WithGeneric[T] {
def ev: Generic[T]
}
case class Impl()
object Impl extends WithGeneric[Impl] {
def ev: Generic[Impl] = Generic[Impl]
}
这是一个小样板,但在不了解您的用例的情况下,我猜这可能是您最好的选择。
下面的简单程序在现成的 scala 2.12 和 shapeless 2.3.2 下无法编译:
import shapeless.Generic
object InferGeneric {
class WithGeneric[T](implicit ev: Generic[T])
case class Impl() {}
object Impl extends WithGeneric[Impl]
}
编译器抛出以下错误:
/.../InferGeneric.scala:11: super constructor cannot be passed a self reference unless parameter is declared by-name
object Impl extends WithGeneric[Impl]
有趣的是,当 object Impl
重命名后,它可以毫无问题地编译。似乎通用推理中使用的宏在与伴随对象组合时会导致一些循环解析。如何避免这种情况?
非常感谢您的意见!
问题是宏生成的代码,但它并不是真正特定于宏的。您可以使用明确定义的实例重现该问题:
import shapeless._
class WithGeneric[T](implicit ev: Generic[T])
case class Impl()
object Impl extends WithGeneric[Impl]()(
new Generic[Impl] {
type Repr = HNil
def to(p: Impl): Repr = HNil
def from(p: Repr): Impl = Impl()
}
)
或者如果您想确保没有涉及宏:
trait Generic[A] { def mk: A }
class WithGeneric[T](ev: Generic[T])
case class Impl()
object Impl extends WithGeneric[Impl](
new Generic[Impl] { def mk: Impl = Impl() }
)
通常,在实例化 Impl
伴随对象时,您将无法在构造函数调用中传递调用 Impl.apply
的代码。
如果不进一步了解您要使用 WithGeneric
做什么,就很难提出解决方法。在像这样的简单情况下,您可以显式定义 Generic[Impl]
并仅使用 new Impl
构造函数(而不是 Impl.apply
)。如果您想要的是能够提供具有抽象大小写定义的伴随对象便捷方法 类,您可以这样做:
import shapeless._
abstract class WithGeneric[T] {
def ev: Generic[T]
}
case class Impl()
object Impl extends WithGeneric[Impl] {
def ev: Generic[Impl] = Generic[Impl]
}
这是一个小样板,但在不了解您的用例的情况下,我猜这可能是您最好的选择。