Shapeless:在 KList 上映射自然变换
Shapeless: Mapping an natural transformation over a KList
有没有办法将自然变换(例如 Option ~> Either[String, *]
)映射到 KList(例如 HList
和 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)
}
我知道缺少的部分是执行 .map
所需的 Mapper
并且 Shapeless 无法从 myNaturalTransformation
的案例和 UnaryTCConstraint
.是否可以通过其他方式获得?或者是否有另一种方法来映射我忽略的 KList(除了将 Mapper
传递给 doStuff
-函数)?
我能够编写自己的 UnaryTCConstraint
版本,其中包括
def mapper[G[_], HF <: ~>[TC, G]](hf: HF): Mapper[hf.type, L]
为给定的自然变换显式生成映射器。但是我很好奇是否可以通过 Shapeless 的 UnaryTCConstraint
.
实现来做到这一点
UnaryTCConstraint
(*->*
) 不是用于映射,它是一个约束(常见于 HList
s、Coproduct
s、case classes 和密封特性)。对于映射,有 classes NatTRel
、Mapped
、Comapped
、Mapper
等类型(HList
s 和 Coproduct
s).
同时尝试约束和类型 class
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)
}
或通过存在隐藏类型参数L
(但return类型不精确)
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
有没有办法将自然变换(例如 Option ~> Either[String, *]
)映射到 KList(例如 HList
和 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)
}
我知道缺少的部分是执行 .map
所需的 Mapper
并且 Shapeless 无法从 myNaturalTransformation
的案例和 UnaryTCConstraint
.是否可以通过其他方式获得?或者是否有另一种方法来映射我忽略的 KList(除了将 Mapper
传递给 doStuff
-函数)?
我能够编写自己的 UnaryTCConstraint
版本,其中包括
def mapper[G[_], HF <: ~>[TC, G]](hf: HF): Mapper[hf.type, L]
为给定的自然变换显式生成映射器。但是我很好奇是否可以通过 Shapeless 的 UnaryTCConstraint
.
UnaryTCConstraint
(*->*
) 不是用于映射,它是一个约束(常见于 HList
s、Coproduct
s、case classes 和密封特性)。对于映射,有 classes NatTRel
、Mapped
、Comapped
、Mapper
等类型(HList
s 和 Coproduct
s).
同时尝试约束和类型 class
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)
}
或通过存在隐藏类型参数L
(但return类型不精确)
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