1

有没有办法将自然变换(例如 a Option ~> Either[String, *])映射到 KList (例如 aHList和 a UnaryTCConstraint)上?对于 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)
}

我知道缺少的部分是Mapper执行 s 所必需的,.map并且 Shapeless 无法从myNaturalTransformations 案例和UnaryTCConstraint. 是否有可能通过其他方式获得?或者是否有另一种方法来映射我忽略的 KList(除了将 a 传递MapperdoStuff-function)?

我能够编写自己的版本,UnaryTCConstraint其中包括

def mapper[G[_], HF <: ~>[TC, G]](hf: HF): Mapper[hf.type, L]

为给定的自然变换显式生成映射器。但是我很好奇是否可以通过 Shapeless 的UnaryTCConstraint.

4

1 回答 1

2

UnaryTCConstraint( *->*) 不用于映射,它是一个约束(常见于HLists、Coproducts、案例类和密封特征)。对于映射,有类型类NatTRelMappedComappedMapper(分别用于HLists 和Coproducts)。

尝试约束和类型类

def doStuff[KList <: HList: *->*[Option]#λ, L <: HList](klist: KList)(implicit 
  natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = natTRel.map(myNaturalTransformation, klist)

或者只是输入类

def doStuff[KList <: HList, L <: HList](klist: KList)(implicit 
  natTRel: NatTRel[KList, Option, L, Either[String, *]]
): L = natTRel.map(myNaturalTransformation, klist)

L或通过PartiallyApplied模式隐藏类型参数

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)
}

或通过存在隐藏类型参数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 compile
于 2020-10-31T15:51:32.057 回答