如何在Poly1中操作FieldTypes?

时间:2015-08-22 00:09:13

标签: scala shapeless

我想在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))
}

1 个答案:

答案 0 :(得分:3)

您想将FieldType[K, Option[V]]转换为Option[FieldType[K, V]]FieldType[K, Option[V]]是[{1}}的子类型,您可以将Option[V]转换为V FieldType[K, V]

然后您可以将此操作放入shapeless.labelled.field

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

所以,他们是一样的。