给定更高阶函数,该函数采用类型(A,A)=>的函数。布尔值作为参数:
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中有效以及我做错了什么。
答案 0 :(得分:3)
def gtr[T <% Ordered[T]](a : T, b : T) : Boolean = {
a > b
}
[T <% Ordered[T]]
可以理解为“ T
可以查看 Ordered[T]
” (扩展或隐式转换)。
此方法现已弃用https://issues.scala-lang.org/browse/SI-7629),因此您可以使用隐式证据将T
转换为Ordered[T]
def gtr[T](a : T, b : T)(implicit toOrdered: T => Ordered[T]) : Boolean
一篇非常好的帖子,它详细解释了视图界限:What are Scala context and view bounds?
关于你的第二和第三个问题:在第二个例子中,你需要推断x和y的类型以使代码编译。第3名 - 只是第2名的语法糖。 他们俩都会编译。
isSorted(Array(1,2,3,4,5,6), ((x : Int,y: Int) => x > y))
isSorted(Array(1,2,3,4,5,6), ((_: Int) > (_: Int)))
答案 1 :(得分:3)
问题是你的类型参数A
没有限制,这意味着你可以传递任何类型。但这不可能,因为并非所有类型都有>
方法,就像你说的那样。也没有其他类型>
继承的泛型类型。剩下的唯一选择是类型类,我们有Ordering类型类。您需要在方法的签名中要求Ordering[A]
存在(隐式)。
我会为greater
方法执行此操作,但需要注意一点。我们需要讨论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