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

时间:2017-01-05 03:52:54

标签: scala shapeless

使用Shapeless,我尝试通过以下方式获取Generic[F]

import shapeless._

class F(x: Int)

但失败了:

scala> Generic[F]
<console>:20: error: could not find implicit value for parameter gen: shapeless.Generic[F]
       Generic[F]
              ^

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

1 个答案:

答案 0 :(得分: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
  }
}

如另一个答案所述,您可以通过将类更改为案例类来让Shapeless为您提供实例。但这不是唯一的方法 - 你也可以将构造函数参数更改为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

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

据我所知,有哪些类定义安排得到Generic实例的确切细节没有在任何地方记录(并且the source并不容易阅读),但它很容易通过在REPL中尝试特定案例来测试您感兴趣的限制。