2

我想使用Shapeless 库中的SYB实现来编写以下通用遍历函数:

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写吗?

4

1 回答 1

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)
于 2013-11-03T13:05:57.063 回答