복붙노트

[SCALA] 이 싱글 타입은 싱글 종류 증명할 수있는 동안 발생 타입의 클래스 인스턴스

SCALA

이 싱글 타입은 싱글 종류 증명할 수있는 동안 발생 타입의 클래스 인스턴스

나는 볼품의 부산물의 모든 종류의 싱글 타입임을 증명하는 타입의 클래스를 가지고 가정 :

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)

이제 우리는 우리에게 우리의 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 [푸] 작업을하지만, 그렇지 않습니다. 우리는 이유에 대한 몇 가지 정보를 얻을 수 -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 분명하지만, 싱글 타입이다. 우리는 단지 재미를 위해 수동 범위에 증인 인스턴스를 넣어 시도 할 수 있습니다 :

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 매크로 방법에 의해 생성 된 사람이하지 않는 동안 이런 경우는 이러한 맥락에서 일을 왜 이해가 안 돼요. 여기 무슨 일이야? 수동으로 생성자를 열거 우리를 필요로하지 않는 편리한 해결 방법이 있습니까?

해결법

  1. ==============================

    1.가장 최근의 무형의 2.1.0-SNAPSHOT의로 작성된이 작동합니다.

    가장 최근의 무형의 2.1.0-SNAPSHOT의로 작성된이 작동합니다.

  2. from https://stackoverflow.com/questions/25838411/cant-prove-that-singleton-types-are-singleton-types-while-generating-type-class by cc-by-sa and MIT license