2017-09-23 125 views
0

下面是一個例子模式與類型參數匹配一定到最終類

def maybeeq[A <: String](x: A):A = x match { 
    case z:A => x 
} 

它編譯過程中產生的以下錯誤消息

Error:(27, 12) scrutinee is incompatible with pattern type; found : A required: String case z:A => x

我可以把任何最終類成A的結合來重現錯誤。

爲什麼這個編譯非終結類,但最終失敗?爲什麼輸入擦除不只是用String替換A?

編輯:

注:這種結合可以讓我傳遞字符串類型的值「X」參數。所以'x'可以只是一個字符串,不必是字符串的子類型,所以我不要求編譯器編譯具有不正確簽名的方法。在現實世界的代碼中,我只是將String放在A參數上,但從實驗的角度來看,我很感興趣,爲什麼需要在現有限制(基於最終類本質)之上的這種額外限制。

回答

1

最終集體不能extended.so爲def maybeeq[A <: String](x: A)不是一個正確的語法,因爲Stringfinal,應該不會存在任何亞型String延伸。編譯器巧妙地指出了這個問題。

+0

但x參數可以只是一個字符串,並通過綁定檢查。我不明白爲什麼編譯器需要限制這種情況。 –

+0

'A <:String'表示'A'是'String'的子類型,由於'String'是最終類型,'A'只能是'String'類型,所以爲什麼不直接使用'String'類型? – chengpohi

+0

從實際角度來看,你是對的,但我想知道爲什麼需要額外的限制。我認爲這種限制通常是爲了防止開發人員犯運行時錯誤,但在這種特定情況下,由於類的最終性質,這種錯誤是不可能的。因此,看起來現有限制之上的一個限制並沒有任何實際意義。 –

4

TBH這是一個關於編譯器的設計問題只能由那些誰實施這種檢查

回答有a test在編譯器測試套件,requires such error to be shown。它與被丟棄的類型信息有關,其中具體類型不能被分配給變量,但其原因不能從該測試的git blame中理解。


我將指出,但是,仍然有許多方法來滿足A <: String沒有A在編譯時被稱爲是一個String。首先,NullNothing滿足,處於Scala類型層次結構的底部。這兩者在類型匹配中被明確禁止。另一個例子是多一點涉及:

val UhOh: { type T <: String } = new { type T = String } 
implicitly[UhOh.T <:< String] // satisfies type bound 
implicitly[UhOh.T =:= String] // won't compile - compiler cannot prove the type equality 

這類似於一些newtyping圖案,例如shapeless.tag

在所有這些可能性中,只有一個可以做任何合理的事情是A =:= String,因爲String是在運行時可以實際檢查的唯一類型。哦,除非在匹配中使用通用類型 - 根本不起作用(至少在範圍內不包含ClassTag),因爲這些類型通過擦除消除。

+0

順便說一句,似乎你提到的測試是有關的問題,當存在類型不能擴展到本地上下文沒有類型成員存在,因此不能用於模式匹配。我不是100%肯定的,但如果你有興趣,你可以在這裏找到一些解釋https://typelevel.org/blog/2015/07/16/method-equiv.html –

相關問題