【问题标题】:implicit resolution for a function argument函数参数的隐式解析
【发布时间】:2015-08-30 23:02:19
【问题描述】:

我尝试在 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))
  }
}

然后我尝试将mergesort重新实现为

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] =&gt; List[A],但我传入了List[A] =&gt; implicit Ordering[A] =&gt; List[A],但我不知道如何利用它来实现我在generalizedMergesort 及其本身方面实现mergesort 的目标。

【问题讨论】:

    标签: scala implicit context-bound


    【解决方案1】:

    简单的解决方案是从方法中提取隐式到上层方法:

    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)
    }
    

    【讨论】:

      【解决方案2】:

      您可以通过将调用mergesort 的函数传递给generalizedMergeSort 来克服这个问题。此调用将捕获隐含的Ordering

      def mergesort[A: Ordering](as: List[A]): List[A] = {
        generalizedMergeSort(as, mergesort(_: List[A]))
      }
      

      mergesort(_: List[A]) 是一个List[A] =&gt; List[A] 类型的闭包函数,它用它的参数调用mergesort,隐含的Ordering 参数在这个闭包中被捕获。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 1970-01-01
        • 2012-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-01
        相关资源
        最近更新 更多