2015-02-08 19 views
2

我學習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是Ordered。但我不知道我會把約束放在哪裏。 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) 
                 ^

我怎樣才能得到這個工作?

+2

只需添加到其他的答案,如果你需要傳遞一個函數*左右,並保持通用的,而你把它傳遞*,你必須使用像[不成形聚(HTTP一招://計算器的.com /問題/ 28206295 /理解-單態 - 例如 - 的-不成形)。 – lmm 2015-02-08 08:33:07

+0

@Pater Winton是的,像「無形」這樣的東西在某些情況下可以使生活更簡單......但現在關注於理解Scala和函數式編程本身。現在不要考慮流浪到無形土地。 – 2015-02-08 10:27:17

回答

2
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) 
+2

解決方案是正確的,但它沒有連接到類型擦除,因爲它與運行時類型無關 - 「M.isSorted」這裏只是一個簡短形式的'M.isSorted _' - 在Scala中的eta-expansion沒有推斷泛型類型 - 但它只是Scala的限制 - 例如,Haskell將推斷泛型類型A,對於'M.curry'也是如此,最後從'Array(1,2,3)'參數綁定'Int' - 但scala可以'噸做到這一點 - 見http://stackoverflow.com/questions/27652463/1-listnothing-in-foldleft – dk14 2015-02-08 07:31:14

+0

@ dk14感謝清除我的一個更多的誤解。這正是我愛Stackoverflow的原因。 :) – 2015-02-08 07:40:02

+0

謝謝@SarveshKumarSingh,這工作。 「我不認爲這是定義這些功能的最好方式,但在這種情況下。」你會怎麼做?什麼是「斯卡拉方式」? – 2015-02-08 19:28:21