通用[A]其中A是一个类?

Kev*_*ith 2 scala shapeless

使用Shapeless,我试图获得一个Generic[F]通道:

import shapeless._

class F(x: Int)
Run Code Online (Sandbox Code Playgroud)

但它失败了:

scala> Generic[F]
<console>:20: error: could not find implicit value for parameter gen: shapeless.Generic[F]
       Generic[F]
              ^
Run Code Online (Sandbox Code Playgroud)

可以无形生产Generic[F]?如果是这样,怎么样?

Tra*_*own 6

你想要什么代表F?你可以说它应该是HNil,但是在x类的主体之外是不可见的,所以Shapeless决定不提供任何实例.这只是一个设计决策 - 在我看来是正确的,但很容易想象Shapeless HNil为你的班级提供实例.

定义自己的实例也是相当容易的F,这是可能的,因为Generic它只是另一个类型类:

import shapeless._

class F(x: Int)

object F {
  implicit val genericF: Generic.Aux[F, HNil] = new Generic[F] {
    type Repr = HNil

    def from(r: HNil): F = new F(0)
    def to(t: F): HNil = HNil
  }
}
Run Code Online (Sandbox Code Playgroud)

正如另一个答案所指出的,您可以通过将类更改为案例类来让Shapeless为您提供实例.这不是唯一的方法,但是你也可以将构造函数参数更改为a val或只删除它:

scala> class F(val x: Int)
defined class F

scala> shapeless.Generic[F]
res0: shapeless.Generic[F]{type Repr = shapeless.::[Int,shapeless.HNil]} = anon$macro$3$1@73e5dfa9

scala> class F()
defined class F

scala> shapeless.Generic[F]
res1: shapeless.Generic[F]{type Repr = shapeless.HNil} = anon$macro$5$1@4e0e355c
Run Code Online (Sandbox Code Playgroud)

但是,您无法使参数成为a var或使类成为抽象(除非它已被密封且具有案例类或对象实现).或者你可以,但是你必须再次定义自己的实例,并且你将在Generic文档中违反合同,该文档说明特征类型应该是一个"不可变数据类型,具有规范的构造方式和解构实例".

据我所知,关于类定义的哪种排列方式将获得Generic实例的具体细节未在任何地方记录(并且来源不易阅读),但通过尝试测试您感兴趣的限制非常容易REPL中的具体案例.