未应用可输入的隐含

时间:2017-07-30 10:36:12

标签: scala shapeless

有人可以分享一下有关为什么以下编辑得很好的一些见解:

import shapeless.Typeable._
import shapeless._
import shapeless.labelled.FieldType
import shapeless.record._
import shapeless.tag.@@

trait Typeables[L <: HList] extends DepFn0 {
  type Out <: HList
}

object Typeables {
  type Aux[L <: HList, Out0 <: HList] = Typeables[L] {type Out = Out0}

  def apply[L <: HList](implicit typeables: Typeables[L]): typeables.type = typeables

  implicit def hnilTypeables[L <: HNil]: Aux[L, HNil] = new Typeables[L] {
    type Out = HNil

    def apply(): Out = HNil
  }

  implicit def hlistTypeables[K, V, Rest <: HList]
  (implicit
   head: Typeable[V]
   , tail: Typeables[Rest]
  ): Aux[FieldType[K, V] :: Rest, Typeable[V] :: tail.Out] = new Typeables[FieldType[K, V] :: Rest] {
    type Out = Typeable[V] :: tail.Out

    def apply(): Out =
      head :: tail()
  }
}

object Testy {
  /** Typeable instance for `T @@ U`. */
  implicit def taggedTypeable[T, U]
  (implicit
   castT: Typeable[T]
   , castU: Typeable[U]): Typeable[T @@ U] =
    new Typeable[T @@ U] {
      def cast(t: Any): Option[T @@ U] = {
        if (t == null) None
        else if (t.isInstanceOf[T]) {
          val o = t.asInstanceOf[T]
          Some(tag[U](o))
        } else None
      }

      def describe = s"${castT.describe} @@ ${castU.describe}"
    }

  the[Typeable[Long @@ String]]
  the[Typeables[Record.`'test ->  Long`.T]]
  //  the[Typeables[Record.`'test ->  Long @@ String`.T]]
}

而在第二行the[Typeables[Record.`'test -> Long @@ String`.T]]中的注释会产生编译错误:

Error:(56, 8) could not find implicit value for parameter t: Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil] the[Typeables[Record.`'test -> Long @@ String`.T]] Error:(56, 8) not enough arguments for macro method apply: (implicit t: Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil])Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil] in object the. Unspecified value parameter t. the[Typeables[Record.`'test -> Long @@ String`.T]]

使用scala 2.12.3,无形2.3.2。

我原本期望它能够处理带有标记字段类型的记录,因为我已经为任何标记类型提供了正确的隐式def,并证明它可以自行运行。我错过了什么?

1 个答案:

答案 0 :(得分:1)

T @@ UT with Tagged[U]的同义词。

并且

Record.`'test ->  Long`.T 

FieldType[Symbol @@ "test", Long] :: HNil的缩写。

所以

the[Typeables[Record.`'test ->  Long @@ String`.T]]

可以改写为

the[Typeables[FieldType[Symbol @@ "test", Long @@ String] :: HNil]]

(无论它意味着什么)和这个工作

所以FieldType[Symbol @@ ..., ...] :: HNilRecord. ... .T或多或少是等效的语法,显然@@并不总是在Record. ... .T内正确运作。

(此处我使用了Typelevel Scala和scalac标记-Yliteral-types来处理literal types。)