简体   繁体   English

在未应用中找不到Scala无形状的Generic.Aux隐式参数

[英]Scala shapeless Generic.Aux implicit parameter not found in unapply

I encountered the following problem with implicits in Scala, using Shapeless's Generic.Aux : 我遇到了以下问题与斯卡拉implicits,用无形的Generic.Aux

  case class Complex(re: Double, im: Double)

  object Prod2 {
    def unapply[C, A, B](c: C)(implicit C: Generic.Aux[C, A :: B :: HNil]) = Some((C.to(c).head, C.to(c).tail.head))
  }

  val c = Complex(1.0, 2.0)
  val Prod2(re, im) = c

The code above does not compile. 上面的代码无法编译。 It reports 它报告

Error:(22, 7) could not find implicit value for parameter C: shapeless.Generic.Aux[nexus.ops.Test.Complex,A :: B :: shapeless.HNil]
  val Prod2(re, im) = c
Error:(22, 7) not enough arguments for method unapply: (implicit C: shapeless.Generic.Aux[nexus.ops.Test.Complex,A :: B :: shapeless.HNil])Some[(A, B)].
Unspecified value parameter C.
  val Prod2(re, im) = c

However, if I manually do 但是,如果我手动执行

implicitly[Generic.Aux[Complex, Double :: Double :: HNil]]

it is perfectly OK to derive this implicit instance. 派生此隐式实例完全可以。

The following code works: 以下代码有效:

import shapeless.ops.hlist.IsHCons
import shapeless.{::, Generic, HList, HNil}

case class Complex(re: Double, im: Double)

object Prod2 {
  def unapply[C, L <: HList, H, T <: HList, H1, T1 <: HList](c: C)(implicit
    C: Generic.Aux[C, L],
    isHCons: IsHCons.Aux[L, H, T],
    isHCons1: IsHCons.Aux[T, H1, T1]) = Some((C.to(c).head, C.to(c).tail.head))
}

val c = Complex(1.0, 2.0)
val Prod2(re, im) = c

Unfortunately the compiler simply isn't smart enough to perform the unification that would be necessary to infer A and B here. 不幸的是,编译器根本不够聪明,无法执行此处推断AB所需的统一。 You can read about some of the details of this problem in section 4.3 of Underscore's Type Astronaut's Guide to Shapeless . 您可以在Underscore类型宇航员无变形指南的 4.3节中了解有关此问题的一些详细信息。 The book provides a workaround using IsHCons , but in this case I think requiring a <:< proof is a little cleaner: 本书提供了使用IsHCons的解决方法,但在这种情况下,我认为要求<:<证明更干净:

import shapeless.{::, Generic, HList, HNil}

case class Complex(re: Double, im: Double)

object Prod2 {
  def unapply[C, L <: HList, A, B](c: C)(implicit
    C: Generic.Aux[C, L],
    ev: L <:< (A :: B :: HNil)
  ) = Some((C.to(c).head, C.to(c).tail.head))
}

And then: 接着:

scala> val c = Complex(1.0, 2.0)
c: Complex = Complex(1.0,2.0)

scala> val Prod2(re, im) = c
re: Double = 1.0
im: Double = 2.0

It's disappointing, but this is a workaround you'll need over and over if you work with Shapeless, so it's good to have it in your toolbox. 令人失望,但这是您需要反复使用Shapeless的一种解决方法,因此最好将其放在工具箱中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM