[SCALA] 볼품에 반복적으로 이기종 목록에 케이스 클래스를 변환하려고 이상한 행동
SCALA볼품에 반복적으로 이기종 목록에 케이스 클래스를 변환하려고 이상한 행동
나는이 볼품없는 문제를 알아 내려고 지난 밤에 너무 늦게 방법을 체재하고 나는 내 가슴을 하차하지 않으면 내 저녁을 먹을 것 걱정, 그래서 여기에 표시됩니다.
이 최소화 버전에서는 그냥 반복적으로 이기종 목록으로 케이스 클래스를 변환하는 타입의 클래스를 정의하고 있습니다 :
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
}
현실을 사용해보십시오! 먼저 우리는 몇 가지 경우 클래스가 필요합니다 :
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)
그리고 (나는이 완전히 읽을 수 엉망 없다는 위해서 유형 구문을 정리 한 참고)
scala> DeepHLister[A :: HNil]
res0: DeepHLister[A :: HNil]{
type Out = (Int :: String :: HNil) :: HNil
} = DeepHLister$$anon$2@634bf0bf
scala> DeepHLister[B :: HNil]
res1: DeepHLister[B :: HNil] {
type Out = (
(Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil
) :: HNil
} = DeepHLister$$anon$2@69d6b3e1
scala> DeepHLister[C :: HNil]
res2: DeepHLister[C :: HNil] {
type Out = (
((Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil) ::
(Int :: String :: HNil) ::
HNil
) :: HNil
} = DeepHLister$$anon$2@4d062faa
여태까지는 그런대로 잘됐다. 하지만:
scala> DeepHLister[D :: HNil]
res3: DeepHLister[D :: HNil] {
type Out = ((Int :: String :: HNil) :: B :: HNil) :: HNil
} = DeepHLister$$anon$2@5b2ab49a
B 조 변환되지 않았다. 우리가 -Xlog-implicits 켜면이 마지막 메시지입니다 :
<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]
^
ME-headCaseClassDeepHLister 이해가되지 않는 것은 DeepHLister 생성 할 수 있어야 어느 [B를 :: HNil] 잘, 당신은 직접 물어 경우가 않습니다.
이 2.10.4 및 2.11.2 및 2.0.0 릴리스와 마스터 모두 모두에서 발생합니다. 나는이 버그가 수 있도록이 있는지 꽤 있어요,하지만 난 뭔가 잘못하고 있어요 가능성을 배제하고 있지 않다. 사람이 전에 이런 것을 본 적이 있습니까? 내 논리 또는 내가 부족 일반에 대한 몇 가지 제한 사항이이 뭔가 잘못인가?
좋아요, 감사에 대한 청취 - 어쩌면 지금은 책이나 뭔가를 읽어 갈 수 있습니다.
해결법
-
==============================
1.이제이 더 많거나 적게 최근 무형의-2.1.0-SNAPSHOT을 사용하여 작성된로 작동 구축하고,이 문제의 샘플의 가까운 친척을 예로 들어이 추가되었습니다.
이제이 더 많거나 적게 최근 무형의-2.1.0-SNAPSHOT을 사용하여 작성된로 작동 구축하고,이 문제의 샘플의 가까운 친척을 예로 들어이 추가되었습니다.
원래의 문제는 일반의 각 확장은 원칙적으로 관련되는 HList 유형을 생산할 수의 DeepHLister 타입의 클래스 인스턴스의 암시 해상도에 새로운 HList 유형을 소개하고 있다는 것입니다하지만시 이전에 본 어떤 종류보다 더 복잡 동일한 해상도. 이 조건은 발산 검사기를 여행하고 확인 프로세스를 중단합니다.
이 D에 대한하지만 C는 대략적인 근사치로, 스칼라의 typechecker의 구현의 세부 사항에 숨어 있지만에 대한 발생 이유의 정확한 세부 사항은 차별화 C의 해상도 동안 우리는 A 전에 B를 (더)를 참조하십시오이다 발산 검사기가 우리의 유형을 수렴하는 행복 그래서 (작은); 반대로 D의 해상도 중 우리가 전에 B는 A를 (작은) 참조 (큰) 발산 검사기 (보수적) 보석금 그래서.
엉성한 2.1.0에서 이에 대한 수정이 최근 개선 된 레이지 형 생성자와 관련된 암시 매크로 인프라. 이 차이를 통해 더 많은 사용자가 제어 할 수 있으며, 재귀 유형에 자동으로 파생 형 클래스 인스턴스 할 수있는 기능에 매우 중요하다 재귀 암시 값을 구성하는 암시 적 해상도의 사용을 지원합니다. 이 많은 예는 무형의 코드베이스에서 찾을 수 있습니다 특히 재 작업 유형 클래스 파생 인프라와 스크랩 더 이상 전용 매크로 지원을 필요로하지만, 일반 및 게으른 프리미티브의 측면에서 완전히 구현 귀하의 상용구의 구현입니다. 이러한 메커니즘의 다양한 응용 프로그램은 무형의 예 하위 프로젝트에서 찾을 수 있습니다.
-
==============================
2.나는 약간 다른 접근 방식을했다.
나는 약간 다른 접근 방식을했다.
trait CaseClassToHList[X] { type Out <: HList } trait LowerPriorityCaseClassToHList { implicit def caseClass[X](implicit gen: Generic[X]): CaseClassToHList[X] { type Out = generic.Repr } = null } object CaseClassToHList extends LowerPriorityCaseClassToHList { type Aux[X, R <: HList] = CaseClassToHList[X] { type Out = R } implicit def caseClassWithCaseClasses[X, R <: HList]( implicit toHList: CaseClassToHList.Aux[X, R], nested: DeepHLister[R]): CaseClassToHList[X] { type Out = nested.Out } = null } trait DeepHLister[R <: HList] { type Out <: HList } object DeepHLister { implicit def hnil: DeepHLister[HNil] { type Out = HNil } = null implicit def caseClassAtHead[H, T <: HList]( implicit head: CaseClassToHList[H], tail: DeepHLister[T]): DeepHLister[H :: T] { type Out = head.Out :: tail.Out } = null def apply[X <: HList](implicit d: DeepHLister[X]): d.type = null }
다음 코드로 테스트 :
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) object Test { val z = DeepHLister[HNil] val typedZ: DeepHLister[HNil] { type Out = HNil } = z val a = DeepHLister[A :: HNil] val typedA: DeepHLister[A :: HNil] { type Out = (Int :: String :: HNil) :: HNil } = a val b = DeepHLister[B :: HNil] val typedB: DeepHLister[B :: HNil] { type Out = ((Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil) :: HNil } = b val c = DeepHLister[C :: HNil] val typedC: DeepHLister[C :: HNil] { type Out = (((Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil) :: (Int :: String :: HNil) :: HNil) :: HNil } = c val d = DeepHLister[D :: HNil] val typedD: DeepHLister[D :: HNil] { type Out = ((Int :: String :: HNil) :: ((Int :: String :: HNil) :: (Int :: String :: HNil) :: HNil) :: HNil) :: HNil } = d }
from https://stackoverflow.com/questions/25923974/weird-behavior-trying-to-convert-case-classes-to-heterogeneous-lists-recursively by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 튜플 매개 변수 선언과 할당 기이 (0) | 2019.11.07 |
---|---|
[SCALA] 예외 : ZLIB 입력 스트림의 예기치 않은 종료 (0) | 2019.11.07 |
[SCALA] 어떻게 디스크에 CSV로 스파크 DataFrame을 저장? (0) | 2019.11.07 |
[SCALA] 스칼라 람다 함수에서 _의 사용 (0) | 2019.11.07 |
[SCALA] 자바 scala.collection.immutable.Map에 java.util.HashMap에 변환 (0) | 2019.11.06 |