给定一个接受类型为 (A,A) => Boolean 的函数作为参数的高阶函数:
def isSorted[A](as: Array[A], ordered : (A,A) => Boolean) : Boolean =
{
def doSorted(i: Int) : Boolean =
if (i >= as.length-1) true
else if (ordered(as(i), as(i+1))) false
else doSorted(i+1)
doSorted(0)
}
val lst1 = Array(1,2,3,4,5,6)
我可以声明一个具有已知参数类型的函数并将其传入:
def gtr(a : Int, b : Int) : Boolean = {
a > b
}
isSorted(lst1,gtr) /* works :-) */
我想执行以下操作之一。这些似乎都不适合我:
使用参数化类型的函数:
def gtr[T](a : T, b : T) : Boolean = { a > b /* gives value > is not a member of type parameter T */ }
这在 Scala 中可能吗?我必须告诉编译器 T 是 继承自具有 > 运算符的对象?
使用匿名函数:
isSorted(lst1, ((x,y) => x > y)) /* gives missing parameter type */
使用 Scala 下划线魔术来传递 > 运算符
isSorted(lst1, _>_) /* gives missing parameter type */
这三个选项都不适合我,我正在努力找出原因。谁能告诉我上述哪些方法在 Scala 中有效以及我做错了什么。
最佳答案
问题是你的类型参数 A
没有限制,也就是说你可以传递任何类型。但那不可能,因为并非每种类型都有 >
方法,就像你说的那样。也没有其他具有 >
的类型继承自的泛型类型。剩下的唯一选项是类型类,我们有 Ordering类型类。您将需要要求在您的方法签名中(隐含地)存在 Ordering[A]
。
我会为 greater
方法做这件事,但有一个警告。我们需要柯里化(Currying) isSorted
的参数。
def isSorted[A](as: Array[A])(ordered: (A, A) => Boolean): Boolean = {
def doSorted(i: Int) : Boolean =
if (i >= as.length - 1) true
else if (ordered(as(i), as(i + 1))) false
else doSorted(i + 1)
doSorted(0)
}
现在我们定义 greater
来隐式找到一个 Ordering[A]
。一旦我们有了一个,我们就可以使用它的 gt
方法进行实际比较。
def greater[A: Ordering](a: A, b: A): Boolean = implicitly[Ordering[A]].gt(a, b)
这等同于:
def greater[A](a: A, b: A)(implicit ord: Ordering[A]): Boolean = ord.gt(a, b)
用法:
scala> isSorted(Array(1, 2, 3, 4))(greater _)
res88: Boolean = true
scala> isSorted(Array(1, 4, 3, 4))(greater _)
res89: Boolean = false
关于scala - Scala 中参数化类型的运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30062968/