scala - 找不到 shapeless.ops.record.Selector 的隐含值
问题描述
我正在玩无形以探索在无形标记记录中提取值类型的可能性。动机是我可以使用类型类和隐式来根据类型分派流程。但是,以下代码不起作用。
import shapeless._, record._
import shapeless.ops.record.Selector
import shapeless.syntax.RecordOps
import shapeless.syntax.singleton._
object ShapelessRecordTest extends App {
trait Extractor[K, T] {
type OUT_K
def extract: T => OUT_K
}
object Extractor {
type Aux[K, T, OUT_K0] = Extractor[K, T] {
type OUT_K = OUT_K0
}
implicit def apply[T, Repr, OUT](k: Witness)(
implicit gen: LabelledGeneric.Aux[T, Repr],
selector: Selector.Aux[Repr, k.T, OUT]
): Aux[k.T, T, OUT] = new Extractor[k.T, T] {
type OUT_K = OUT
def extract: T => OUT_K = (e: T) => {
val rep = gen.to(e)
val rprOp: RecordOps[Repr] = new RecordOps[Repr](rep)
rprOp(k)
}
}
}
case class Person(name: String, address: String, age: Int)
implicit val gen = LabelledGeneric[Person]
val nameWit: Witness = 'name
val nameExtractor: Extractor.Aux[nameWit.T, Person, String] = Extractor(nameWit)
def main(args: Array[String]): Unit = {
val joe = Person("Joe", "Brighton", 33)
println(nameExtractor.extract(joe))
}
}
我正在使用 Scala 2.12.8,编译器错误是
{
"resource": "/workspace/connecterra/stream-data-pipeline/flink/src/main/scala/io/connecterra/ShapelessRecordTest.scala",
"owner": "_generated_diagnostic_collection_name_#0",
"severity": 8,
"message": "could not find implicit value for parameter selector: shapeless.ops.record.Selector.Aux[Repr,ShapelessRecordTest.nameWit.T,OUT]",
"source": "scalac",
"startLineNumber": 37,
"startColumn": 74,
"endLineNumber": 37,
"endColumn": 75
}
我想了解我在这里缺少什么。还是完全有可能是无形的?
解决方案
apply
如果您要显式调用它,那么隐含的意义不大。最好不要混合定义类型类的实例化方法和隐式方法。RecordOps
不应该手动创建(有import shapeless.record._
那个)。有时最好直接调用apply
类型类(例如shapeless.ops.record.Selector
)的方法,而不是依赖扩展方法。当你写val nameWit: Witness = 'name
你松散的类型细化。创造没有意义implicit val gen = LabelledGeneric[Person]
。对于Selector
,Repr
应该是<: HList
。
尝试
import shapeless._
import shapeless.ops.record.Selector
object ShapelessRecordTest {
trait Extractor[K, T] {
type OUT_K
def extract: T => OUT_K
}
object Extractor {
type Aux[K, T, OUT_K0] = Extractor[K, T] {
type OUT_K = OUT_K0
}
def apply[T](k: Witness)(implicit
extractor: Extractor[k.T, T]): Aux[k.T, T, extractor.OUT_K] = extractor
implicit def extractor[T, Repr <: HList, K](implicit
gen: LabelledGeneric.Aux[T, Repr],
selector: Selector[Repr, K]
): Aux[K, T, selector.Out] = new Extractor[K, T] {
type OUT_K = selector.Out
def extract: T => OUT_K = (e: T) => {
val rep: Repr = gen.to(e)
selector(rep)
}
}
}
case class Person(name: String, address: String, age: Int)
val nameWit = Witness('name)
val nameExtractor: Extractor.Aux[nameWit.T, Person, String] = Extractor(nameWit)
def main(args: Array[String]): Unit = {
val joe = Person("Joe", "Brighton", 33)
println(nameExtractor.extract(joe)) // Joe
}
}
推荐阅读
- arrays - 数据列表中的动态数组未显示
- java - 如何在 SSLContextBuilder.create().loadTrustMaterial 的 JUnit 测试中引发异常?
- php - 如何只允许数组中的数据进入输入字段?
- powershell - Powershell IE自动化如何传递标志来导航方法?
- macos - 如何在 Quartz 事件中读取鼠标增量?
- javascript - 显示 JSON 对象
- youtube-dl - Youtube-dl @只想将播放列表(文件名列表)下载到文本文件
- cordova - 来自 PhotoGallery iOS13 的 UIWebView 输入视频
- css - 禁用按钮的 CSS 使用 :not() 排除某个类
- c# - 无法在进程 dll 模块的入口点写入 1 个字节