gpt4 book ai didi

scala - 映射一个无形的 HList 的类型

转载 作者:行者123 更新时间:2023-12-04 15:19:38 25 4
gpt4 key购买 nike

我一直在尝试映射 HList 的类型来自斯卡拉的 shapeless包而无法访问它们的值。

以下成功映射了 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]
}

}

如何获得映射的类型 HList没有访问它的值(value)?有没有办法调试为什么编译器不能证明什么?谢谢阅读。

最佳答案

TestListActualMappedType的情况下你有 mappedList 的单例类型,这与 mappedList 的推断类型不同.您可以在不涉及 Shapeless 的情况下看到完全相同的问题:

scala> val x = "foo"
x: String = foo

scala> implicitly[x.type =:= String]
<console>:13: error: Cannot prove that x.type =:= String.
implicitly[x.type =:= String]
^

你可以要求提供 x.type 的证据是 String 的子类型或者你可以使用 shapeless.test.typed ,在您的情况下看起来像这样:
import shapeless._, 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
}

trait lpvfun extends Poly1 {
implicit def default[A <: Person] = at[A](_.v)
}

object vfun extends lpvfun {}

val stringPerson = StringPerson()
val intPerson = IntPerson()

val testList = stringPerson :: intPerson :: HNil
val mappedList = testList map vfun

shapeless.test.typed[String :: Int :: HNil](mappedList)

不过,这并没有因为明确指定类型而真正为您买单。

您可以要求提供诸如 Mapper 这样的类型类的输出类型的证据。是您期望的特定输入类型的类型:
scala> val m = Mapper[vfun.type, StringPerson :: IntPerson :: HNil]
m: shapeless.ops.hlist.Mapper[vfun.type,shapeless.::[StringPerson,shapeless.::[IntPerson,shapeless.HNil]]]{type Out = shapeless.::[String,shapeless.::[Int,shapeless.HNil]]} = shapeless.ops.hlist$Mapper$$anon$5@6f3598cd

scala> implicitly[m.Out =:= (String :: Int :: HNil)]
res1: =:=[m.Out,shapeless.::[String,shapeless.::[Int,shapeless.HNil]]] = <function1>

这更有可能有用,但同样取决于您试图说服自己的确切内容。

关于scala - 映射一个无形的 HList 的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39822856/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com