函数参数的隐式解析
implicit resolution for a function argument
我尝试在 Scala 中实现归并排序。我得到以下内容:
def mergeSort[A: Ordering](as: List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(mergeSort(l), mergeSort(r))
}
}
def split[A](as: List[A]): (List[A], List[A]) = {
def rec(todo: List[A], done: (List[A], List[A])): (List[A], List[A]) = todo match {
case Nil => done
case head :: tail => rec(tail, (head :: done._2, done._1))
}
rec(as, (Nil, Nil))
}
def merge[A: Ordering](left: List[A], right: List[A]) = {
def rec(left: List[A], right: List[A], done: List[A]): List[A] =
(left, right) match {
case (_, Nil) => rprepend(left, done)
case (Nil, _) => rprepend(right, done)
case (lh :: lt, rh :: rt) => if (implicitly[Ordering[A]].compare(lh, rh) <= 0)
rec(lt, right, lh :: done)
else rec(left, rt, rh :: done)
}
rec(left, right, Nil).reverse
}
def rprepend[A](prepend: List[A], as: List[A]): List[A] =
prepend.foldLeft(as)((r, a) => a :: r)
这个问题不是关于正在进行的大量低效逆向,也不是关于缺少尾递归。相反,我注意到您可以通过传入排序算法来概括合并排序,如下所示:
def generalizedMergeSort[A: Ordering](as: List[A], sort: List[A] => List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(sort(l), sort(r))
}
}
然后我尝试重新实现合并排序
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort)
}
但是编译失败,找不到合适的 Ordering[A]
:
[error] test.scala:17: No implicit Ordering defined for A.
[error] generalizedMergeSort(as, mergesort)
[error] ^
作为将事情纳入范围的微弱尝试,我尝试了
def mergesort[A: Ordering](as: List[A]): List[A] = {
implicit val realythere = implicitly[Ordering[A]]
generalizedMergeSort(as, mergesort)
}
但无济于事。
我怀疑问题出在generalizedMergesort
的第二个参数上。我说参数是 List[A] => List[A]
,但我传入了 List[A] => implicit Ordering[A] => List[A]
,但我不知道如何利用它来实现我的目标 mergesort
generalizedMergesort
和它自己。
简单的解决方案是从方法提取隐式到上层方法:
def mergesort[A: Ordering](as: List[A]): List[A] = {
def mergesort0(xs: List[A]): List[A] = generalizedMergeSort(xs, mergesort0)
mergesort0(as)
}
第二个是用隐式包装你的函数(通过额外的对象创建):
def mergesort[A: Ordering](as: List[A]): List[A] = {
val mergesort0: List[A] => List[A] = xs => mergesort(xs)
generalizedMergeSort(as, mergesort0)
}
您可以通过将调用 mergesort
的函数传递给 generalizedMergeSort
来解决这个问题。此调用将捕获隐式 Ordering
:
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort(_: List[A]))
}
mergesort(_: List[A])
是一个 List[A] => List[A]
类型的闭包函数,它用它的参数调用 mergesort
,隐式的 Ordering
参数在这个闭包中被捕获。
我尝试在 Scala 中实现归并排序。我得到以下内容:
def mergeSort[A: Ordering](as: List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(mergeSort(l), mergeSort(r))
}
}
def split[A](as: List[A]): (List[A], List[A]) = {
def rec(todo: List[A], done: (List[A], List[A])): (List[A], List[A]) = todo match {
case Nil => done
case head :: tail => rec(tail, (head :: done._2, done._1))
}
rec(as, (Nil, Nil))
}
def merge[A: Ordering](left: List[A], right: List[A]) = {
def rec(left: List[A], right: List[A], done: List[A]): List[A] =
(left, right) match {
case (_, Nil) => rprepend(left, done)
case (Nil, _) => rprepend(right, done)
case (lh :: lt, rh :: rt) => if (implicitly[Ordering[A]].compare(lh, rh) <= 0)
rec(lt, right, lh :: done)
else rec(left, rt, rh :: done)
}
rec(left, right, Nil).reverse
}
def rprepend[A](prepend: List[A], as: List[A]): List[A] =
prepend.foldLeft(as)((r, a) => a :: r)
这个问题不是关于正在进行的大量低效逆向,也不是关于缺少尾递归。相反,我注意到您可以通过传入排序算法来概括合并排序,如下所示:
def generalizedMergeSort[A: Ordering](as: List[A], sort: List[A] => List[A]): List[A] = as match {
case Nil => as
case head :: Nil => as
case _ => {
val (l, r) = split(as)
merge(sort(l), sort(r))
}
}
然后我尝试重新实现合并排序
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort)
}
但是编译失败,找不到合适的 Ordering[A]
:
[error] test.scala:17: No implicit Ordering defined for A.
[error] generalizedMergeSort(as, mergesort)
[error] ^
作为将事情纳入范围的微弱尝试,我尝试了
def mergesort[A: Ordering](as: List[A]): List[A] = {
implicit val realythere = implicitly[Ordering[A]]
generalizedMergeSort(as, mergesort)
}
但无济于事。
我怀疑问题出在generalizedMergesort
的第二个参数上。我说参数是 List[A] => List[A]
,但我传入了 List[A] => implicit Ordering[A] => List[A]
,但我不知道如何利用它来实现我的目标 mergesort
generalizedMergesort
和它自己。
简单的解决方案是从方法提取隐式到上层方法:
def mergesort[A: Ordering](as: List[A]): List[A] = {
def mergesort0(xs: List[A]): List[A] = generalizedMergeSort(xs, mergesort0)
mergesort0(as)
}
第二个是用隐式包装你的函数(通过额外的对象创建):
def mergesort[A: Ordering](as: List[A]): List[A] = {
val mergesort0: List[A] => List[A] = xs => mergesort(xs)
generalizedMergeSort(as, mergesort0)
}
您可以通过将调用 mergesort
的函数传递给 generalizedMergeSort
来解决这个问题。此调用将捕获隐式 Ordering
:
def mergesort[A: Ordering](as: List[A]): List[A] = {
generalizedMergeSort(as, mergesort(_: List[A]))
}
mergesort(_: List[A])
是一个 List[A] => List[A]
类型的闭包函数,它用它的参数调用 mergesort
,隐式的 Ordering
参数在这个闭包中被捕获。