私は、scalaのshapeless
パッケージからHList
の型をその値にアクセスすることなくマップしようとしました。シェイプレスな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
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]
}
}
どのように1は、その値にアクセスすることなく、マップされたHList
の種類を取得していますか?コンパイラが何かを証明できない理由をデバッグする方法はありますか?読んでくれてありがとう。
ありがとうございます - これは本当に役立ちます。 2番目のコードブロックでは、コンパイル時に 'm'はどうなりますか?それは最適化されていますか? 'm.Out'が実際に値を作成せずに持つ型を得る方法はありますか? – user1158559