'diverging implicit expansion'-foldleft HList 错误
'diverging implicit expansion'-error on foldleft HList
我正在尝试进行类型计算以构建一些嵌套的集合结构,但是当我尝试使用以 List[T] 作为键的类似 Map 的集合时出现 'diverging implicit expansion for type shapeless.ops.hlist.LeftFolder' 错误或值类型。此嵌套结构有效:
import shapeless._
import shapeless.ops.hlist._
object poly extends Poly2 {
implicit def wrapMap[T] = at[T, Int]((end, t) => Map(t -> end))
//other collection wrap functions
}
def foldToNestedCollections[T <: HList, Out](hl: T)(implicit lf: LeftFolder.Aux[T, Any, poly.type, Out]): Out = lf.apply(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //compiles
这个结构给出了错误:
import shapeless._
import shapeless.ops.hlist._
object poly extends Poly2 {
implicit def wrapMap[T] = at[T, Int]((end, t) => Map(List(t) -> end)) //or Map(t, List(end)) gives the same error
//other collection wrap functions
}
def foldToNestedCollections[T <: HList, Out](hl: T)(implicit lf: LeftFolder.Aux[T, Any, poly.type, Out]): Out = lf.apply(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //does not compile 'diverging ...
更新:
如果我构建一个自定义转换器,它就可以工作。我使用之前问题 的答案来构建它。任何建议为什么?
import shapeless._
import shapeless.ops.hlist._
sealed trait MyLeftFolder[L <: HList, T] {
type Out
def convert(hlist: L, value: T): Out
}
object MyLeftFolder {
type Aux[L <: HList, T, Out2] = MyLeftFolder[L, T] { type Out = Out2 }
private trait Impl[L <: HList, T, Out2] extends MyLeftFolder[L, T] {
override type Out = Out2
}
implicit def hnil[T]: Aux[HNil, T, T] = new Impl[HNil, T, T] {
override def convert(hlist: HNil, value: T): T = value
}
implicit def hnil2[T]: Aux[HNil.type, T, T] = new Impl[HNil.type, T, T] {
override def convert(hlist: HNil.type, value: T): T = value
}
implicit def recurseint[L <: HList, T](implicit inner: MyLeftFolder[L, T]): Aux[Int :: L, T, Map[List[Int], inner.Out]] = new Impl[Int :: L, T, Map[List[Int], inner.Out]] {
override def convert(hlist: Int :: L, value: T): Map[List[Int], inner.Out] = {
val im = inner.convert(hlist.tail, value)
Map(List(hlist.head) -> im)
}
}
}
def foldToNestedCollections[T <: HList](hl: T)(implicit lf: MyLeftFolder[T, Any]): lf.Out = lf.convert(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //compiles
使用以下自定义 LeftFolder
而不是标准 shapeless.ops.hlist.LeftFolder
。 Lazy
.
用法不同
import shapeless.{::, DepFn2, HList, HNil, Lazy, Poly2}
import shapeless.poly.Case2
trait LeftFolder[L <: HList, In, HF] extends DepFn2[L, In] with Serializable
object LeftFolder {
def apply[L <: HList, In, F](implicit folder: LeftFolder[L, In, F]): Aux[L, In, F, folder.Out] = folder
type Aux[L <: HList, In, HF, Out0] = LeftFolder[L, In, HF] { type Out = Out0 }
implicit def hnilLeftFolder[In, HF]: Aux[HNil, In , HF, In] =
new LeftFolder[HNil, In, HF] {
type Out = In
def apply(l : HNil, in : In): Out = in
}
implicit def hlistLeftFolder[H, T <: HList, In, HF, OutH, FtOut]
(implicit f : Case2.Aux[HF, In, H, OutH], ft : Lazy[LeftFolder.Aux[T, OutH, HF, FtOut]]): Aux[H :: T, In, HF, FtOut] =
new LeftFolder[H :: T, In, HF] {
type Out = FtOut
def apply(l : H :: T, in : In) : Out = ft.value(l.tail, f(in, l.head))
}
}
我正在尝试进行类型计算以构建一些嵌套的集合结构,但是当我尝试使用以 List[T] 作为键的类似 Map 的集合时出现 'diverging implicit expansion for type shapeless.ops.hlist.LeftFolder' 错误或值类型。此嵌套结构有效:
import shapeless._
import shapeless.ops.hlist._
object poly extends Poly2 {
implicit def wrapMap[T] = at[T, Int]((end, t) => Map(t -> end))
//other collection wrap functions
}
def foldToNestedCollections[T <: HList, Out](hl: T)(implicit lf: LeftFolder.Aux[T, Any, poly.type, Out]): Out = lf.apply(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //compiles
这个结构给出了错误:
import shapeless._
import shapeless.ops.hlist._
object poly extends Poly2 {
implicit def wrapMap[T] = at[T, Int]((end, t) => Map(List(t) -> end)) //or Map(t, List(end)) gives the same error
//other collection wrap functions
}
def foldToNestedCollections[T <: HList, Out](hl: T)(implicit lf: LeftFolder.Aux[T, Any, poly.type, Out]): Out = lf.apply(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //does not compile 'diverging ...
更新:
如果我构建一个自定义转换器,它就可以工作。我使用之前问题
import shapeless._
import shapeless.ops.hlist._
sealed trait MyLeftFolder[L <: HList, T] {
type Out
def convert(hlist: L, value: T): Out
}
object MyLeftFolder {
type Aux[L <: HList, T, Out2] = MyLeftFolder[L, T] { type Out = Out2 }
private trait Impl[L <: HList, T, Out2] extends MyLeftFolder[L, T] {
override type Out = Out2
}
implicit def hnil[T]: Aux[HNil, T, T] = new Impl[HNil, T, T] {
override def convert(hlist: HNil, value: T): T = value
}
implicit def hnil2[T]: Aux[HNil.type, T, T] = new Impl[HNil.type, T, T] {
override def convert(hlist: HNil.type, value: T): T = value
}
implicit def recurseint[L <: HList, T](implicit inner: MyLeftFolder[L, T]): Aux[Int :: L, T, Map[List[Int], inner.Out]] = new Impl[Int :: L, T, Map[List[Int], inner.Out]] {
override def convert(hlist: Int :: L, value: T): Map[List[Int], inner.Out] = {
val im = inner.convert(hlist.tail, value)
Map(List(hlist.head) -> im)
}
}
}
def foldToNestedCollections[T <: HList](hl: T)(implicit lf: MyLeftFolder[T, Any]): lf.Out = lf.convert(hl, 1)
foldToNestedCollections(2 :: HNil) //compiles
foldToNestedCollections(2 :: 3 :: HNil) //compiles
使用以下自定义 LeftFolder
而不是标准 shapeless.ops.hlist.LeftFolder
。 Lazy
.
import shapeless.{::, DepFn2, HList, HNil, Lazy, Poly2}
import shapeless.poly.Case2
trait LeftFolder[L <: HList, In, HF] extends DepFn2[L, In] with Serializable
object LeftFolder {
def apply[L <: HList, In, F](implicit folder: LeftFolder[L, In, F]): Aux[L, In, F, folder.Out] = folder
type Aux[L <: HList, In, HF, Out0] = LeftFolder[L, In, HF] { type Out = Out0 }
implicit def hnilLeftFolder[In, HF]: Aux[HNil, In , HF, In] =
new LeftFolder[HNil, In, HF] {
type Out = In
def apply(l : HNil, in : In): Out = in
}
implicit def hlistLeftFolder[H, T <: HList, In, HF, OutH, FtOut]
(implicit f : Case2.Aux[HF, In, H, OutH], ft : Lazy[LeftFolder.Aux[T, OutH, HF, FtOut]]): Aux[H :: T, In, HF, FtOut] =
new LeftFolder[H :: T, In, HF] {
type Out = FtOut
def apply(l : H :: T, in : In) : Out = ft.value(l.tail, f(in, l.head))
}
}