如何操作 Poly1 中的 FieldTypes?
How to manipulate FieldTypes in Poly1?
我想在 Labeled Generics 上使用来自 shapeless contrib (+scalaz) 的序列,但首先我需要映射到 FieldTypes。
是否可以在该示例中创建缺少的 f 函数?
object TestLabelledGeneric {
import shapeless._
import singleton._
val a = "name" ->> Option("hello") :: "y" ->> Option(1) :: HNil
val b = Option("name" ->> "hello") :: Option("y" ->> 1) :: HNil
val f = ???
val name = Witness('name); val age = Witness('age)
def assertTypedEquals[A](expected: A, actual: A): Unit = assert(expected == actual)
assertTypedEquals[b.type](b, a.map(f))
}
已解决,谢谢@travis-brown!
这是在我的机器上运行的版本:
object TestLabelledGeneric {
import shapeless._
import singleton._
val a = "name" ->> Option("hello") :: "y" ->> Option(1) :: HNil
val b = Option("name" ->> "hello") :: Option("y" ->> 1) :: HNil
import labelled.{ FieldType, field }
object f extends Poly1 {
implicit def kv[K, V]: Case.Aux[
FieldType[K, Option[V]],
Option[FieldType[K, V]]
] =
at(_.map(field[K](_)))
}
// If I try to use Witness.`"name"`.T directly in Res, I have a "not accessible type" error
val name = Witness.`"name"`
val y = Witness.`"y"`
type Res = Option[FieldType[name.T, String]] :: Option[FieldType[y.T ,Int]] :: HNil
def assertTypedEquals[A](expected: A, actual: A): Unit = assert(expected == actual)
assertTypedEquals[Res](b, a.map(f))
}
您想将 FieldType[K, Option[V]]
转换为 Option[FieldType[K, V]]
。 FieldType[K, Option[V]]
是 Option[V]
的子类型,您可以使用 shapeless.labelled.field
.
将 V
变成 FieldType[K, V]
然后你可以把这个操作变成一个Poly1
:
import shapeless._, labelled.{ FieldType, field }, syntax.singleton._
object f extends Poly1 {
implicit def kv[K, V]: Case.Aux[
FieldType[K, Option[V]],
Option[FieldType[K, V]]
] =
at(_.map(field[K](_)))
}
这并不能满足您的需求,因为 a.map(f)
的类型不是 b.type
(这是 b
的单例类型)。不过,您可以确认它确实按照您的要求进行操作:
scala> type Res =
| Option[FieldType[Witness.`"name"`.T, String]] ::
| Option[FieldType[Witness.`"y"`.T, Int]] :: HNil
defined type alias Res
scala> assertTypedEquals[Res](b, a.map(f))
是的,它们是一样的。
我想在 Labeled Generics 上使用来自 shapeless contrib (+scalaz) 的序列,但首先我需要映射到 FieldTypes。
是否可以在该示例中创建缺少的 f 函数?
object TestLabelledGeneric {
import shapeless._
import singleton._
val a = "name" ->> Option("hello") :: "y" ->> Option(1) :: HNil
val b = Option("name" ->> "hello") :: Option("y" ->> 1) :: HNil
val f = ???
val name = Witness('name); val age = Witness('age)
def assertTypedEquals[A](expected: A, actual: A): Unit = assert(expected == actual)
assertTypedEquals[b.type](b, a.map(f))
}
已解决,谢谢@travis-brown!
这是在我的机器上运行的版本:
object TestLabelledGeneric {
import shapeless._
import singleton._
val a = "name" ->> Option("hello") :: "y" ->> Option(1) :: HNil
val b = Option("name" ->> "hello") :: Option("y" ->> 1) :: HNil
import labelled.{ FieldType, field }
object f extends Poly1 {
implicit def kv[K, V]: Case.Aux[
FieldType[K, Option[V]],
Option[FieldType[K, V]]
] =
at(_.map(field[K](_)))
}
// If I try to use Witness.`"name"`.T directly in Res, I have a "not accessible type" error
val name = Witness.`"name"`
val y = Witness.`"y"`
type Res = Option[FieldType[name.T, String]] :: Option[FieldType[y.T ,Int]] :: HNil
def assertTypedEquals[A](expected: A, actual: A): Unit = assert(expected == actual)
assertTypedEquals[Res](b, a.map(f))
}
您想将 FieldType[K, Option[V]]
转换为 Option[FieldType[K, V]]
。 FieldType[K, Option[V]]
是 Option[V]
的子类型,您可以使用 shapeless.labelled.field
.
V
变成 FieldType[K, V]
然后你可以把这个操作变成一个Poly1
:
import shapeless._, labelled.{ FieldType, field }, syntax.singleton._
object f extends Poly1 {
implicit def kv[K, V]: Case.Aux[
FieldType[K, Option[V]],
Option[FieldType[K, V]]
] =
at(_.map(field[K](_)))
}
这并不能满足您的需求,因为 a.map(f)
的类型不是 b.type
(这是 b
的单例类型)。不过,您可以确认它确实按照您的要求进行操作:
scala> type Res =
| Option[FieldType[Witness.`"name"`.T, String]] ::
| Option[FieldType[Witness.`"y"`.T, Int]] :: HNil
defined type alias Res
scala> assertTypedEquals[Res](b, a.map(f))
是的,它们是一样的。