J'ai essayé de mapper les types d'un HList
du paquet shapeless
de scala sans avoir accès à leurs valeurs.Mapper les types d'un HList sans forme
qui suit parvient à cartographier les valeurs d'un 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]
}
}
Cool! En plus de ne pas pouvoir utiliser implicitly[A =:= B]
pour une raison quelconque, les valeurs d'un HList
ont été mappées et ont donc leurs types. Maintenant, supposons que nous n'ayons pas la valeur HList
mais nous connaissons son type. Comment pouvons-nous cartographier sur ses types?
J'ai essayé les éléments suivants en fonction de la définition de 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]
}
}
Comment peut-on obtenir le type d'un tracé HList
sans avoir accès à sa valeur? Y at-il un moyen de déboguer pourquoi le compilateur ne peut pas prouver quelque chose? Merci pour la lecture.
Merci, cela aide vraiment. Dans votre deuxième bloc de code, qu'advient-il de 'm' au moment de la compilation? Est-ce optimisé? Est-il possible d'obtenir le type que 'm.Out' aurait sans créer de valeurs? – user1158559