有人可以分享一下有关为什么以下编辑得很好的一些见解:
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,并证明它可以自行运行。我错过了什么?
答案 0 :(得分:1)
T @@ U
是T 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 @@ ..., ...] :: HNil
和Record. ... .T
或多或少是等效的语法,显然@@
并不总是在Record. ... .T
内正确运作。
(此处我使用了Typelevel Scala和scalac标记-Yliteral-types
来处理literal types。)