scaler의 shapeless
패키지에서 HList
의 타입을 값에 액세스하지 않고 매핑하려고했습니다.모양이없는 HList 타입 매핑하기
다음은
import shapeless._
import shapeless.Poly._
import ops.hlist.Mapper
import ops.hlist.Mapper._
trait Person {
type Value
val v : Value
}
case class StringPerson extends Person {
type Value = String
val v = "I like strings"
}
case class IntPerson extends Person {
type Value = Int
val v = 42
}
object what_is_going_on {
object test_value_op {
val stringPerson = StringPerson()
val intPerson = IntPerson()
trait lpvfun extends Poly1 {
implicit def default[A <: Person] = at[A](_.v)
}
object vfun extends lpvfun {}
// Use these to generate compiler errors if the mapped type is not what we'd expect:
type TestListType = StringPerson :: IntPerson :: HNil
type TestListExpectedMappedType = String :: Int :: HNil
// Input:
val testList : TestListType = stringPerson :: intPerson :: HNil
// Output:
val mappedList : TestListExpectedMappedType = testList map vfun
// Get the actual mapped type
type TestListActualMappedType = mappedList.type
// This compiles......
val mappedList1 : TestListActualMappedType = mappedList
// .... but weirdly this line doesn't. That isn't the point of this question, but I'd be very grateful for an answer.
//implicitly[TestListActualMappedType =:= TestListExpectedMappedType]
}
}
쿨 HList의 값을 매핑에 성공! 어떤 이유로 든 implicitly[A =:= B]
을 사용할 수 없다는 것 외에도 HList
의 값이 매핑되어 유형이 있습니다.
이제 우리는 HList
값이 없지만 그 유형을 알고 있다고 가정합니다. 유형을 어떻게 매핑 할 수 있습니까?
map
here의 정의에 따라 다음
object test_type_op {
type TestListType = StringPerson :: IntPerson :: HNil
type TestListExpectedMappedType = String :: Int :: HNil
// Attempt 1 does not work, compiler cannot prove =:=
type MappedType = Mapper[vfun.type, TestListType]#Out
implicitly[MappedType =:= TestListExpectedMappedType]
// Attempt 2 does not work, compiler cannot prove =:=
class GetMapper {
implicit val mapper : Mapper[vfun.type, TestListType]
implicitly[mapper.Out =:= TestListExpectedMappedType]
}
}
어떻게 하나의 값에 액세스 할 필요없이 매핑 HList
의 유형을 얻을 수 있습니까? 왜 컴파일러가 뭔가를 증명할 수없는 디버깅 방법이 있습니까? 읽어 주셔서 감사합니다.
감사합니다. -이게 정말 도움이됩니다. 두 번째 코드 블록에서 컴파일 할 때'm'은 어떻게됩니까? 최적화되어 있습니까? 'm.Out'가 실제로 값을 만들지 않고 가질 수있는 타입을 얻는 방법이 있습니까? – user1158559