我想使用SYB中的Shapeless library实现来编写以下通用遍历函数:
class Data
// Perform the desired manipulation on the given data
object manipulate extends ->((data: Data) => data)
def traverseAndManipulate[B](expr: B): B = {
everywhere(manipulate)(expr)
}
不幸的是,此代码产生以下类型错误(使用Shapeless 2.0.0-M1和Scala 2.10.2):
type mismatch;
[error] found : shapeless.EverywhereAux[SYB.manipulate.type]
[error] required: ?{def apply(x$1: ? >: B): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error] both method inst1 in trait PolyInst of type [A](fn: shapeless.Poly)(implicit cse: fn.ProductCase[shapeless.::[A,shapeless.HNil]])A => cse.Result
[error] and macro method apply in object Poly of type (f: Any)shapeless.Poly
[error] are possible conversion functions from shapeless.EverywhereAux[SYB.manipulate.type] to ?{def apply(x$1: ? >: B): ?}
[error] everywhere(manipulate)(expr)
我假设,类型参数B
需要以某种方式进行约束,以使Shapeless库的隐式宏适用,但我不知道如何。
可以使用Shapeless编写这样的遍历函数吗?
答案 0 :(得分:3)
您需要为方法正文中可用的任何组合器做一个隐含的见证,
def traverseAndManipulate[B](expr: B)
(implicit e: Everywhere[manipulate.type, B]) = everywhere(manipulate)(expr)
请注意,由于我目前无法理解的原因,给traverseAndManipulate
显式结果类型B
会导致编译器报告类似的歧义。但是,结果类型正确推断为B
。如果您希望具有显式结果类型,则以下内容应相同,
def traverseAndManipulate[B](expr: B)
(implicit e: Everywhere[manipulate.type, B] { type Result = B }): B = e(expr)