我一直在尝试映射 scala 的 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]
}
}
很棒!除了因某些原因无法使用
implicitly[A =:= B]
之外,一个HList
的值已经被映射,它们的类型也一样。现在,如果我们没有
HList
的值,但我们知道它的类型,如何映射它的类型?根据这里
map
的定义(链接),我尝试了以下方法: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