ile ardışık olarak vaka sınıflarını heterojen listelere dönüştürmeye çalışırken garip davranışlar Geçen gece bu Shapeless sorununu anlamaya çalışmak için çok geç kaldım ve korkarım ki, eğer bunu başaramazsam akşamımı yiyeceğimden korkuyorum Göğsüm, işte burada. Bu minimize versiyondaGarip davranışlar, Shapeless
Sadece heterogeneous listeler halinde yinelemeli durum sınıfları dönüştürecek bir tip sınıfını tanımlayan ediyorum:
import shapeless._
trait DeepHLister[R <: HList] extends DepFn1[R] { type Out <: HList }
trait LowPriorityDeepHLister {
type Aux[R <: HList, Out0 <: HList] = DeepHLister[R] { type Out = Out0 }
implicit def headNotCaseClassDeepHLister[H, T <: HList](implicit
dht: DeepHLister[T]
): Aux[H :: T, H :: dht.Out] = new DeepHLister[H :: T] {
type Out = H :: dht.Out
def apply(r: H :: T) = r.head :: dht(r.tail)
}
}
object DeepHLister extends LowPriorityDeepHLister {
implicit object hnilDeepHLister extends DeepHLister[HNil] {
type Out = HNil
def apply(r: HNil) = HNil
}
implicit def headCaseClassDeepHLister[H, R <: HList, T <: HList](implicit
gen: Generic.Aux[H, R],
dhh: DeepHLister[R],
dht: DeepHLister[T]
): Aux[H :: T, dhh.Out :: dht.Out] = new DeepHLister[H :: T] {
type Out = dhh.Out :: dht.Out
def apply(r: H :: T) = dhh(gen.to(r.head)) :: dht(r.tail)
}
def apply[R <: HList](implicit dh: DeepHLister[R]): Aux[R, dh.Out] = dh
}
Şunu deneyelim! Önce bazı örnek sınıfları gerekir:
scala> DeepHLister[A :: HNil]
res0: DeepHLister[A :: HNil]{
type Out = (Int :: String :: HNil) :: HNil
} = [email protected]
scala> DeepHLister[B :: HNil]
res1: DeepHLister[B :: HNil] {
type Out = (
(Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil
) :: HNil
} = [email protected]
scala> DeepHLister[C :: HNil]
res2: DeepHLister[C :: HNil] {
type Out = (
((Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil) ::
(Int :: String :: HNil) ::
HNil
) :: HNil
} = [email protected]
Şimdiye kadar: o zaman
case class A(x: Int, y: String)
case class B(x: A, y: A)
case class C(b: B, a: A)
case class D(a: A, b: B)
Ve (Ben tamamen okunmaz karmaşa olmaması bu uğruna tipi sözdizimi temizledim unutmayın) iyi. Ama sonra:
scala> DeepHLister[D :: HNil]
res3: DeepHLister[D :: HNil] {
type Out = ((Int :: String :: HNil) :: B :: HNil) :: HNil
} = [email protected]
B
dönüştürülür vermedi. Biz -Xlog-implicits
açarsanız bu son mesajdır:
<console>:25: this.DeepHLister.headCaseClassDeepHLister is not a valid implicit value for DeepHLister[shapeless.::[B,shapeless.HNil]] because:
hasMatchingSymbol reported error: diverging implicit expansion for type DeepHLister[this.Repr]
starting with method headNotCaseClassDeepHLister in trait LowPriorityDeepHLister
DeepHLister[D :: HNil]
^
duygusu headCaseClassDeepHLister
DeepHLister[B :: HNil]
gayet üretmek mümkün olmalıdır sonradır için yapmaz ve doğrudan sorarsanız öyle.
Bu, hem 2.10.4 hem de 2.11.2'de ve hem 2.0.0 sürümü hem de master ile gerçekleşir. Bunun bir hata olması gerektiğine eminim, fakat yanlış bir şey yaptığım olasılığını reddetmiyorum. Daha önce böyle bir şey gören oldu mu? Benim mantığım veya Generic
eksikliğimdeki bazı kısıtlamalar var mı?
Tamam, dinlediğiniz için teşekkürler - belki şimdi bir kitap okuyabiliyorum.
DeepLister [B :: HNil] 'ile benzer bir sorunum var. Kodu 5 dakika önce kopyaladım, böylece daha fazla araştırma yapacağım. – EECOLOR
Bu, whitebox makroları ile oldukça kolay olurdu. –
@ GuillaumeMassé, Doğru, kesinlikle, ama amaç Makroların kullanımını Shapeless tarafından sağlanan birkaç temel olanla sınırlamaktır. –