scala - 如何对齐无形记录?
问题描述
给定
case class Foo(a: Int, c: Int)
case class Bar(a: Int, b: Int, c: Int)
我想写一个看起来像这样的函数:
def mkBar(foo: Foo, b: Int): Bar = {
import shapeless.syntax.singleton._
val fooRecords = LabelledGeneric[Foo].to(foo)
val bRecord = 'b ->> b
val allRecords = fooRecords :+ bRecord
// Doesn't work as it's a c b and we need a b c
LabelledGeneric[Bar].from(allRecords)
}
即给定一个Foo 和ab,创建一个Bar。此代码无法编译,因为我附加了“b”而不是将其插入 Hlist 的中间。
我知道我可以使用 anhlist.Align
与 a 对齐,Bar
但我看到的所有示例都显示了两个 Reprs 例如Align[FooGen.Repr, BarGen.Repr]
。在我的情况下,我没有allRecords
实例的Repr,所以我不知道如何派生合适的 Align 实例。
如何将“动态”Hlist 与Repr 对齐?
解决方案
因此解决方案是将代码拆分为另一个带有类型参数和隐式 Align 实例的函数。最后我想出了这个:
object ShapelessOps {
import shapeless._
import shapeless.ops.hlist
trait Converter[A, B] {
def apply(a: A): B
}
implicit class ConverterOps[A](a: A) {
def as[B](implicit converter: Converter[A, B]): B = converter.apply(a)
}
implicit def genericConverter[B, BRepr <: HList, Unaligned <: HList](
implicit
bGen : LabelledGeneric.Aux[B, BRepr],
align : hlist.Align[Unaligned, BRepr]
): Converter[Unaligned, B] = new Converter[Unaligned, B] {
def apply(a: Unaligned): B = bGen.from(align.apply(a))
}
}
我像这样使用它:
val fooRecords = LabelledGeneric[Foo].to(foo)
val bRecord = 'b ->> b
val allRecords = fooRecords :+ bRecord
allRecords.as[Bar]
推荐阅读
- python - 将 ZMQ 事件循环与 QT / Pyforms 事件循环相结合
- java - 在firebase中存储数组/在firebase中查询多个字符串
- xamarin.android - 使用自定义 URL 方案通过浏览器启动 Xamarin Android 应用程序
- javascript - 当参数为某个值时定义返回类型
- docker - Go Webapp 的 Dockerfile 目录结构
- gcc - 编译器如何选择哪个“get_pc_thunk”函数来获取当前地址?
- wifi - (IoT) 为什么 zigbee 智能设备需要额外的网关才能连接到 WAN?
- c# - MVC5 的日期选择器,C#
- vaadin8 - vaadin grid:如何在行之间创建标题
- python - sqlalchemy 引擎对象是否自动处理?