使用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]?如果是这样,怎么样?
你想要什么代表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中的具体案例.