gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 01:25:09 25 4
gpt4 key购买 nike

假设我有一个类型类,可以证明 Shapeless 联积中的所有类型都是单例类型:

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 运行:

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
}
}

我希望隐式[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 显然一个单例类型。我们可以尝试手动将 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.apply 宏方法(我们用来创建它们)生成的实例却不能。这里发生了什么?有没有一种方便的解决方法,不需要我们手动枚举构造函数?

最佳答案

这与最新的 Shapeless 2.1.0-SNAPSHOT 中的编写方式相同。

关于scala - 生成类型类实例时无法证明单例类型是单例类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25838411/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com