2012-01-05 78 views
5

我有點被咖喱和uncurried通用功能之間的類型檢查的區別感到困惑:通用類型的統一:多個參數(T,T)與多個參數列表(T)(T)?

scala> def x[T](a: T, b: T) = (a == b) 
x: [T](a: T, b: T)Boolean 
scala> def y[T](a: T)(b: T) = (a == b) 
y: [T](a: T)(b: T)Boolean 

我的直覺是,這兩個x(1, "one")y(1)("one")應該給類型錯誤,但是我錯了:

scala> x(1, "one") 
res71: Boolean = false 
scala> y(1)("one") 
<console>:9: error: type mismatch; 
found : java.lang.String("one") 
required: Int 
       y(1)("one") 
       ^

起初我還以爲有某種隱式轉換的事情,但似乎並沒有這樣的情況:

scala> x(1 :Int, "one" :String) 
res73: Boolean = false 

那麼這是怎麼回事?我的直覺應該是什麼?

+0

我已經看到了這一個重複很久以前。我也相信這個[幾乎]確切的案例在SLS中有記錄。 – 2012-01-05 20:47:14

+0

我們走了。我已經更新了,因爲'Y(1:任意)的標題與重要術語「多參數列表」,這是在SLS :) – 2012-01-05 20:55:21

回答

9

我認爲,在第一種情況下它上溯造型(向下轉換?)兩個參數,使得T:任何。第二,它是爲Int加捲曲,然後在字符串上失敗。

這似乎證明我:

scala> y(1)_ 
res1: Int => Boolean = <function1> 
+0

好討論的,很可能(「你好」)''返回FALSE'。 – rampion 2012-01-05 20:49:38

+0

看到我的編輯更多的證據 – 2012-01-05 20:52:49

+0

作爲一個有趣的側面說明,這個問題似乎要求在這裏作出斷言:http://www.scala-lang.org/node/262,那麼「f(x )(y)和g(x,y)被編譯成完全相同的代碼。「 – 2012-01-05 21:08:08

10

斯卡拉試圖確定類型一次一個參數塊。你可以看到這個,如果你添加其他參數和部分應用:

def x[T](a: T, b: T)(c: T) = (a == b) 
scala> x(1, "one") _ 
res0: Any => Boolean = <function1> 

當然,無論IntStringAny(和==定義上Any)。未在更早的塊中使用

類型參數保持自由在以後的塊使用:

def y[T,U](a: T)(b: U)(c: (T,U)) = (a == b) 
scala> y(1)("one") 
res1: (Int, java.lang.String) => Boolean = <function1> 

您也可以使用前面塊作爲默認值在以後的塊!

def z[T,U](a: T)(b: U)(c: (T,U) = (a,b)) = (c._1 == c._2) 
scala> z(1)("one")() 
res2: Boolean = false 

因此,將參數分配到多個參數塊中會對類型推斷和默認值(以及部分應用程序)產生影響。