在生成types类实例的时候,不能certificate单例types是单例types

假设我有一个types类来certificate一个Shapeless副产品中的所有types都是单例types:

import shapeless._ trait AllSingletons[A, C <: Coproduct] { def values: List[A] } object AllSingletons { implicit def cnilSingletons[A]: AllSingletons[A, CNil] = new AllSingletons[A, CNil] { def values = Nil } implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit tsc: AllSingletons[A, T], witness: Witness.Aux[H] ): AllSingletons[A, H :+: T] = new AllSingletons[A, H :+: T] { def values = witness.value :: tsc.values } } 

我们可以certificate它适用于一个简单的ADT:

 sealed trait Foo case object Bar extends Foo case object Baz extends Foo 

接着:

 scala> implicitly[AllSingletons[Foo, Bar.type :+: Baz.type :+: CNil]].values res0: List[Foo] = List(Bar, Baz) 

现在我们想把这个与Shapeless的Generic机制结合起来,它会给我们一个ADT的副产品表示:

 trait EnumerableAdt[A] { def values: Set[A] } object EnumerableAdt { implicit def fromAllSingletons[A, C <: Coproduct](implicit gen: Generic.Aux[A, C], singletons: AllSingletons[A, C] ): EnumerableAdt[A] = new EnumerableAdt[A] { def values = singletons.values.toSet } } 

我期望implicitly[EnumerableAdt[Foo]]能够工作,但事实并非如此。 我们可以使用-Xlog-implicits得到一些关于为什么的信息:

 <console>:17: shapeless.this.Witness.apply is not a valid implicit value for shapeless.Witness.Aux[Baz.type] because: Type argument Baz.type is not a singleton type implicitly[EnumerableAdt[Foo]] ^ <console>:17: this.AllSingletons.coproductSingletons is not a valid implicit value for AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]] because: hasMatchingSymbol reported error: could not find implicit value for parameter witness: shapeless.Witness.Aux[Baz.type] implicitly[EnumerableAdt[Foo]] ^ <console>:17: this.AllSingletons.coproductSingletons is not a valid implicit value for AllSingletons[Foo,this.Repr] because: hasMatchingSymbol reported error: could not find implicit value for parameter tsc: AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]] implicitly[EnumerableAdt[Foo]] ^ <console>:17: this.EnumerableAdt.fromAllSingletons is not a valid implicit value for EnumerableAdt[Foo] because: hasMatchingSymbol reported error: could not find implicit value for parameter singletons: AllSingletons[Foo,C] implicitly[EnumerableAdt[Foo]] ^ <console>:17: error: could not find implicit value for parameter e: EnumerableAdt[Foo] implicitly[EnumerableAdt[Foo]] ^ 

Baz.type显然单身types。 为了好玩,我们可以尝试将Witness实例手动放在范围中:

 implicit val barSingleton = Witness[Bar.type] implicit val bazSingleton = Witness[Baz.type] 

不知何故,现在它的作品:

 scala> implicitly[EnumerableAdt[Foo]].values res1: Set[Foo] = Set(Bar, Baz) 

我不明白为什么这些实例会在这种情况下工作,而Witness.applymacros方法(我们用它来创build它们)却没有。 这里发生了什么? 有没有一个方便的解决方法,不需要我们手动枚举构造函数?

这可以像最新的无形2.1.0-SNAPSHOT一样书写。