折叠提供的 HList
Folding over provided HList
我知道我的问题可能是 "XY problem",所以这里简要回顾一下我想要实现的目标。
假设我有以下类型:
trait Provider[T] { def provide: T }
我希望能够将从该类型提供的多个值组合成一个(每个提供的值可以有不同的类型)。组合发生在程序的不同部分,让我们定义类型 Combiner(尝试将 shapeless 应用于我的问题):
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
我得出以下结论:
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(folder, zero)
}
为了指定用于折叠的函数,我创建了辅助方法:
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers]
一切都很好,只是它不起作用。
我正在尝试使用以下代码对其进行测试:
implicit val zero = Json.obj()
//incorrect implementation, but compilation is important here
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly) //compiles
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)//do not compile, LeftFolder.AUX not found
我的问题是:
a) 我该如何解决这个编译问题,或者
b) 有没有 different/better 方法来解决我最初的问题
编辑
事实证明我的错误是由错误的导入引起的,我以某种方式导入了 tuple.LeftFolder 而不是 hlist.LeftFolder,愚蠢的错误
以下代码编译通过
import io.circe.Json
import shapeless.{::, HList, HNil, Poly, Poly2}
import shapeless.ops.hlist.LeftFolder
trait Provider[T] {
def provide: T
}
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(providers, zero)
}
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers, fun.type]
implicit val zero = Json.obj()
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly)
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)
我知道我的问题可能是 "XY problem",所以这里简要回顾一下我想要实现的目标。 假设我有以下类型:
trait Provider[T] { def provide: T }
我希望能够将从该类型提供的多个值组合成一个(每个提供的值可以有不同的类型)。组合发生在程序的不同部分,让我们定义类型 Combiner(尝试将 shapeless 应用于我的问题):
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
我得出以下结论:
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(folder, zero)
}
为了指定用于折叠的函数,我创建了辅助方法:
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers]
一切都很好,只是它不起作用。 我正在尝试使用以下代码对其进行测试:
implicit val zero = Json.obj()
//incorrect implementation, but compilation is important here
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly) //compiles
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)//do not compile, LeftFolder.AUX not found
我的问题是:
a) 我该如何解决这个编译问题,或者
b) 有没有 different/better 方法来解决我最初的问题
编辑
事实证明我的错误是由错误的导入引起的,我以某种方式导入了 tuple.LeftFolder 而不是 hlist.LeftFolder,愚蠢的错误
以下代码编译通过
import io.circe.Json
import shapeless.{::, HList, HNil, Poly, Poly2}
import shapeless.ops.hlist.LeftFolder
trait Provider[T] {
def provide: T
}
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(providers, zero)
}
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers, fun.type]
implicit val zero = Json.obj()
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly)
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)