如何在 Scala 中组合泛型方法?

How can I compose generic methods in Scala?

我正在学习 Scala 并且有以下玩具代码:

object M {
  def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
    xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))

  def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
    (a) => (b) => f(a, b)
}

我的目标是这样称呼它:

M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)

但我收到错误消息:

scala> M.curry(M.isSorted)(Array(1,2,3))
<console>:8: error: type mismatch;
  found   : Int(1)
  required: Nothing
  M.curry(M.isSorted)(Array(1,2,3))

让我们回头看看柯里化函数的类型:

scala> M.curry(M.isSorted)
res2: Array[Nothing] => (((Nothing, Nothing) => Boolean) => Boolean) = <function1>

那可不行。它需要一个 Array[Nothing] 但不能有 Nothing.

的实例

我知道在某些时候我需要引入一个约束,以便编译器可以证明表达式 a < b 是允许的;也就是说,ab 是有序的。但我不知道我会把约束放在哪里。 curry 是完全通用的;约束不属于那里。 isSortedcompare 的实现一无所知,因此它也不属于那里。

我最接近让它工作的是 def isSorted[X >: Any]

scala> M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
<console>:8: error: value < is not a member of Any
  M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
                                                ^

scala> M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
<console>:8: error: type mismatch;
  found   : (Int, Int) => Boolean
  required: (Any, Any) => Boolean
  M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
                                                          ^

我怎样才能让它工作?

object M {
  def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
    xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))

  def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
    (a) => (b) => f(a, b)
}

嗯...我不认为这是定义这些函数的最佳方式,但在这种情况下,因为这些是通用函数,所以您需要在调用时为它们提供类型。

正如@dk14 在他的评论中指出的那样...M.sorted 无法获取类型信息,因为 Scala 缺乏对多态 lambda 的支持...这仅仅意味着匿名函数中没有泛型。

因此您需要针对此特定情况执行此操作。

M.curry( M.isSorted[Int] )( Array(1,2,3) ) ( (a , b) => a < b )