生成类型类实例时无法证明单例类型是单例类型 [英] Can't prove that singleton types are singleton types while generating type class instance

查看:85
本文介绍了生成类型类实例时无法证明单例类型是单例类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类型类,该类型类证明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.

这篇关于生成类型类实例时无法证明单例类型是单例类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆