В следующем коде я пытаюсь получить экземпляры типов с бесформенными. Однако в случае более сложного класса case (который преобразуется в более сложный HList) компилятор дает мне «расходящееся неявное расширение», хотя он, кажется, не разрешает один и тот же тип неявного типа дважды. Может быть, мне не хватает другого правила компилятора?Почему скалак вызывает ошибку «расходящегося неявного расширения»?
(Fiddle: https://scalafiddle.io/sf/WEpnAXN/0)
import shapeless._
trait TC[T]
sealed trait Trait1
case class SimpleClass(a: String) extends Trait1
sealed trait Trait2
case class ComplexClass(a: String, b: String) extends Trait2
object Serialization extends App {
//Instances for HList
implicit val hnilInstance: TC[HNil] = ???
implicit def hconsInstance[H, T <: HList] (implicit t: TC[T]): TC[H :: T] = ???
//Instances for CoProduct
implicit val cnilInstance: TC[CNil] = ???
implicit def cconsInstance[H, T <: Coproduct] (implicit h: TC[H], t: TC[T]): TC[H :+: T] = ???
//Instances for Generic, relying on HNil & HCons
implicit def genericInstance[T, H] (implicit g: Generic.Aux[T, H], t: TC[H]): TC[T] = ???
the[TC[SimpleClass :+: CNil]] //Works
the[TC[Trait1]] //Works
the[TC[ComplexClass :+: CNil]] //Works
the[TC[Trait2]] //Fails with diverging implicit expansion
}
При попытке решить the[TC[Trait1]]
компилятор должен сделать что-то вроде этого:
TC[Trait1]
Generic[Trait1]
TC[SimpleClass :+: CNil]
TC[SimpleClass]
Generic[SimpleClass]
TC[String :: HNil]
TC[CNil]
, который, кажется, работает. Однако, с классом case 2-поля, компилятор не может сделать что-то вроде этого - так что мне интересно: почему я должен использовать Lazy
здесь, чтобы заставить его работать?
TC[Trait2]
Generic[Trait2]
TC[ComplexClass :+: CNil]
TC[ComplexClass]
Generic[ComplexClass]
TC[String :: String :: HNil]
TC[CNil]
Я создал скрипку, чтобы вы могли выполнить код там directy.
Я подозреваю, что ответ Майлза [здесь] (http://stackoverflow.com/a/27911353/334519) является объяснением, хотя случай не совсем такой же, как мой в этом вопросе. –