scala 如何压缩类型的值?

wi3ka0sx  于 2022-12-18  发布在  Scala
关注(0)|答案(1)|浏览(118)

我有一个HList的联产品,如下所示:

(A :+: B :+: CNil) :: (Foo :+: Bar :+: CNil) :: HNil

这个HList * 将 * 是我的程序中的一个值。例如:

val myhlist: (A :+: B :+: CNil) :: (Foo :+: Bar :+: CNil) :: HNil = ???

我还有一个副产品的H列表,看起来像这样:

(A :+: CNil) :: (Bar :+: CNil) :: HNil


然而,这个HList在整个程序中 * 不是 * 一个值;它只存在于类型级别中。
我想用这个压缩函数压缩这两个HList:

def zipFn[A <: Coproduct, B <: Coproduct](a: A)(implicit basis: Basis[A, B]) = {
  a.deembed[B]
}

A是来自前一个HList的元素(在整个程序中都有值),B是来自后一个HList的元素。我想将值(A s)与类型(B s)压缩。
可能是一个很简单的问题,但不知何故,我对此感到困扰?
有什么建议吗?

我目前的想法是在Shapeless中使用curried多态函数;比如:

object myZipFn extends Poly1 {
  implicit def default[A <: Coproduct, B <: Coproduct](implicit basis: Basis[A, B]) = at[A] { a => a.deembed[B] }
}

val curried = Poly.curried(myZipFn)

但是没有多大意义,因为default同时请求A和B。
我的想法是首先泛型地接受B(没有值的类型),然后返回一个新函数,要求将A作为值,然后我们就有了这两个函数。
谢谢

yiytaume

yiytaume1#

.zipWith接受Poly2,而不是Poly1。因此myZipFn应该是

object myZipFn extends Poly2 {
  implicit def default[A <: Coproduct, B <: Coproduct](implicit
    basis: Basis[A, B]
  ): Case.Aux[A, B, basis.Out] = at[A, B] { (a, _) => a.deembed[B] }
}

.zipWith不必要的第二个参数处(因为您只有类型级别的第二个HList,而不是值级别的),您可以替换为空值的HList(但类型正确)

val myhlist: (A :+: B :+: CNil) :: (Foo :+: Bar :+: CNil) :: HNil = ???
type hlist1 = (A :+: CNil) :: (Bar :+: CNil) :: HNil

object nullPoly extends Poly0 {
  implicit def default[A]: Case0[A] = at(null.asInstanceOf[A])
}

val nullHlist: hlist1 = FillWith[nullPoly.type, hlist1].apply()

myhlist.zipWith(nullHlist)(myZipFn)

或者,如果你不想有一个空值的HList,你必须为值/类型级别的第一个参数和类型级别的第二个参数定义自定义的Zip/ZipWith类型类。
FillWith/nullPoly技巧的其他使用情形:
How to obtain all possible members of a coproduct
Scala - looping over case class names to use as type parameters
How to get field names and field types from a Generic Type in Scala?
Is it possible to have a variable type list in Scala?
Get case class field's name and type with shapeless
How to pass into generic type using a Symbol or Type object into a generic typed function?

相关问题