使用从函数返回的Shapeless Nat作为另一个函数的参数

时间:2018-08-15 13:40:08

标签: scala shapeless

我有以下函数,该函数获取形状为 Point(d0,d1,...,dK)的K维点的列表,并返回该范围的维的索引最大。索引返回为 Nat

def findMaxRangeDim[T, H <: HList, L <: HList, K<: HList](data: List[T])(
implicit gen: Generic.Aux[T, H],
zipper: Zip.Aux[H::H::HNil, L],
maxMapper: Mapper.Aux[mergeMaxMap.type, L, H],
minMapper: Mapper.Aux[mergeMinMap.type, L, H],
diffMapper: Mapper.Aux[absDiffMap.type, L, H],
indexZipper: ZipWithIndex.Aux[H, K],
folder: LeftFolder.Aux[K, (BigDecimal, Nat), maxIndexFinder.type, 
(BigDecimal, Nat)]
  ): Nat = {/*implementation*/}

假设我有另一个函数,该函数需要一个数据点和一个 Nat ,并返回位于由 Nat 表示的尺寸处的元素:

def getAt[T, H<:HList, N<:Nat](p: T, n: N)(
    implicit gen: Generic.Aux[T, H],
    at: At.Aux[H, N, BigDecimal]
  ) = {/*implementation*/}

在可以确认:

// This compiles:
  getAt(data.head, Nat._1)

// This doesn't:
  getAt(data.head, findMaxRangeDim(data))

错误是could not find implicit value for parameter at: shapeless.ops.hlist.At.Aux[H,shapeless.Nat,BigDecimal]

我猜想这是因为shapeless正在寻找findMaxRangeDim(data)结果的确切类型的隐式,但这仅在运行时才知道。有什么方法可以隐式传递权限,并在另一个函数中使用结果 Nat

2 个答案:

答案 0 :(得分:0)

您应该修改findMaxRangeDim,使其返回特定的N <: Nat(例如,将其添加为类型参数),而不是仅仅返回Nat(太粗糙了)。

现在getAt(data.head, findMaxRangeDim(data))不起作用,因为没有At.Aux[H, Nat, BigDecimal](但是特定的At.Aux[H, N, BigDecimal]N <: Nat)。

隐式在编译时解决,而不是在运行时解决。

答案 1 :(得分:0)

我通过Dmytro Mitin尝试了该方法,但是编译器只会抱怨找不到正确类型的隐式。

然后我在Shapeless的gitter频道中询问,意识到编译器需要在编译时知道Nat的特定类型。因为我的代码在运行时处找到了正确的Nat,所以编译器无法事先知道要使用哪种类型。

吸取的教训是Nat与典型的Iterables中的索引并不相似。