Scala

时间:2015-05-05 20:46:52

标签: scala

给定更高阶函数,该函数采用类型(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 :-) */

我想做以下其中一项。这似乎都不适合我:

  1. 使用带参数化类型的函数:

     def gtr[T](a : T, b : T) : Boolean = {
          a > b    /* gives value > is not a member of type parameter T */
     }
    

    这在Scala中是否可行。我必须告诉编译器T是 继承自具有>的对象操作

  2. 使用匿名函数:

    isSorted(lst1, ((x,y) => x > y)) /* gives missing parameter type */
    
  3. 使用Scala下划线魔法传递>操作

    isSorted(lst1, _>_) /* gives missing parameter type */
    
  4. 这三个选项都不适合我,我正在努力找出原因。任何人都可以告诉我上述哪些方法在Scala中有效以及我做错了什么。

2 个答案:

答案 0 :(得分:3)

你是对的。您需要指定,可以比较T。 一种方法是使用视图边界:

    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