生成类型类实例时无法证明单例类型是单例类型

编程入门 行业动态 更新时间:2024-10-28 21:29:34
本文介绍了生成类型类实例时无法证明单例类型是单例类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我有一个类型类,该类型类证明Shapeless副产品中的所有类型都是单例类型:

Suppose I've got a type class that proves that all the types in a Shapeless coproduct are singleton 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 } }

我们可以证明它可以与简单的ADT一起使用:

We can show that it works with a simple 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的副产品表示:

Now we want to combine this with Shapeless's Generic mechanism that'll give us a coproduct representation of our 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获取有关原因的一些信息:

I'd expect implicitly[EnumerableAdt[Foo]] to work, but it doesn't. We can use -Xlog-implicits to get some information about why:

<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显然是单例类型.我们可以尝试将Witness实例手动放置在作用域中只是为了好玩:

Baz.type obviously is a singleton type, though. We can try putting the Witness instances in scope manually just for fun:

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

现在它以某种方式起作用:

And somehow now it works:

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

我不明白为什么这些实例在这种情况下会起作用,而Witness.apply宏方法(我们用来创建它们)所生成的实例却不能.这里发生了什么?是否有一个方便的解决方法,不需要我们手动枚举构造函数?

I don't understand why these instances would work in this context while the ones generated by the Witness.apply macro method (which we used to create them) don't. What's going on here? Is there a convenient workaround that doesn't require us to enumerate the constructors manually?

推荐答案

此功能与最新的无形2.1.0-SNAPSHOT相同.

This works as written as of the most recent shapeless 2.1.0-SNAPSHOT.

更多推荐

生成类型类实例时无法证明单例类型是单例类型

本文发布于:2023-11-11 17:38:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1579120.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:类型   实例   是单例

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!