有没有办法将自然转换(例如Option ~> Either[String, *])映射到KList (例如带有UnaryTCConstraint的HList )上?对于KList来说,这似乎是很自然的事情。
具体地说,我试图做到以下几点:
object myNaturalTransformation extends (Option ~> Either[String, *]) {
def apply[T](a: Option[T]): Either[String, T] = a.toRight("oh noe!")
}
def doStuff[KList <: HList: *->*[Option]#λ](klist: KList) = {
klist.map(myNaturalTransformation)
}我知道缺少的部分是执行.map所需的Mapper,Shapeless不能从myNaturalTransformation的案例和UnaryTCConstraint生成一个。有没有可能通过其他方式获得一个呢?或者,有没有其他方法可以映射到我忽略的KList上(除了将Mapper传递给doStuff-function之外)?
我能够编写我自己的UnaryTCConstraint版本,其中包含一个
def mapper[G[_], HF <: ~>[TC, G]](hf: HF): Mapper[hf.type, L]显式地为给定的自然转换生成映射器。然而,我很好奇是否有可能用Shapeless的UnaryTCConstraint实现来做到这一点。
发布于 2020-10-31 23:51:32
UnaryTCConstraint (*->*)不是用来映射的,它是一个约束(在HList、Coproduct、case类和密封特征中很常见)。用于映射的类型类有NatTRel、Mapped、Comapped、Mapper等(分别用于HList和Coproduct)。
同时尝试约束类和类型类
def doStuff[KList <: HList: *->*[Option]#λ, L <: HList](klist: KList)(implicit
natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = natTRel.map(myNaturalTransformation, klist)或者只键入class
def doStuff[KList <: HList, L <: HList](klist: KList)(implicit
natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = natTRel.map(myNaturalTransformation, klist)或者通过PartiallyApplied模式隐藏类型参数L
def doStuff[KList <: HList] = new PartiallyAppliedDoStuff[KList]
class PartiallyAppliedDoStuff[KList <: HList] {
def apply[L <: HList](klist: KList)(implicit
natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = natTRel.map(myNaturalTransformation, klist)
}或者通过existential隐藏类型参数L (但返回类型不精确)
def doStuff[KList <: HList](klist: KList)(implicit
natTRel: NatTRel[KList, Option, _, Either[String, *]]
) = natTRel.map(myNaturalTransformation, klist)或者使用扩展方法
implicit class NatTRelOps[KList <: HList](val klist: KList) extends AnyVal {
def map[F[_], G[_], L <: HList](f: F ~> G)(implicit
natTRel: NatTRel[KList, F, L, G]
): L = natTRel.map(f, klist)
}
def doStuff[KList <: HList, L <: HList](klist: KList)(implicit
natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = klist.map(myNaturalTransformation)测试:
doStuff(Option(1) :: Option("a") :: HNil) // compiles
//doStuff(Option(1) :: Option("a") :: true :: HNil) // doesn't compilehttps://stackoverflow.com/questions/64622828
复制相似问题