2015-05-05 62 views
3

給定一個高階函數,它類型的函數(A,A)=>布爾作爲參數:算上參數化類型Scala中

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. 使用功能與parametrised類型:

    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. 使用斯卡拉強調魔術打發>運營商

    isSorted(lst1, _>_) /* gives missing parameter type */ 
    

這三個選項都不爲我工作,我掙扎找出原因。任何人都可以告訴我哪些上述方法在Scala中是有效的,我做錯了什麼。

回答

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 
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的類型來編譯代碼。第三名 - 僅僅是第二名的語法糖。 他們倆都會編譯。

isSorted(Array(1,2,3,4,5,6), ((x : Int,y: Int) => x > y)) 
isSorted(Array(1,2,3,4,5,6), ((_: Int) > (_: Int)))