2011-07-31 7 views
13

Aşağıdaki Scala kodunu düşünün: Scala, tip parametreleri iç içe geçtiğinde neden türetilen parametreleri tam olarak anlamıyor?

abstract class A 
abstract class B[T <: A] 
class ConcreteA extends A 
class ConcreteB extends B[ConcreteA] 

class Example[U <: B[T], T <: A](resolver: U) 
object Test { 
    new Example(new ConcreteB) 
} 

Son satır new Example(new ConcreteB) aşağıdaki hata ile derlenemiyor:

error: inferred type arguments [ConcreteB,Nothing] do not conform to class Example's type parameter bounds [U <: B[T],T <: A]

Ancak ConcreteB hem U hem de T çözümlemek için gerekli tüm verilere sahiptir. ben burada özlüyorum

+0

olası bir kopyası [Scala'da Nothing türüne yazılır] (http://stackoverflow.com/questions/6888136/type-infered-to-nothing-in-scala) –

+1

Benzer, ancak kabul edilen yanıt Bu durumda soru geçerli değildir. –

cevap

10

Kipton, yüksek kaliteli çözümüyle yakınlaştı. Ne yazık ki, Scala < 2.9.1.RC1'de bir hata olduğu anlaşılan şeyin üzerine attı. Ben kendi öğrenme için GitHub üzerinde a document of type inference workarounds besteledim

Welcome to Scala version 2.9.1.RC1 (Java HotSpot(TM) Server VM, Java 1.7.0). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> abstract class A 
defined class A 

scala> abstract class B[T <: A] 
defined class B 

scala> class ConcreteA extends A 
defined class ConcreteA 

scala> class ConcreteB[T <: A] extends B[T] 
defined class ConcreteB 

scala> class Example[T <: A, U[X <: A] <: B[X]](resolver: U[T]) 
defined class Example 

scala> new Example(new ConcreteB[ConcreteA]) 
res0: Example[ConcreteA,ConcreteB] = [email protected] 
+0

Yakın, ama daha sonra ConcreteB somut değil. Bu, ConcreteB'yi açıkça parametrelemek zorunda kalmadan sizin için işe yarıyor mu? –

+0

Ben çıkarım ConcreteB' 'açık parameterization (ama ilk gayet iyi çalışıyor en bahsettiğim tip üyesi yaklaşımı) olmadan çalışmaya alınamıyor. –

+0

sayesinde, bu noktada alır gibi bu kadar yakın sanırım. –

10

(aynı zamanda iki ilişkili sorulara bakınız: Scala fails to infer the right type arguments ve Type infered to Nothing in Scala)

O kasıtlı spec'ed değildir Scala'nın tür kesmesi, bir sınırlama gibi görünüyor. bir çözüm olarak, sen T bir tip üyesi yerine parametrenin daha B ait yaparak çıkarım alabilirsiniz

abstract class A 
abstract class B { type T <: A } 
class ConcreteA extends A 
class ConcreteB extends B { type T = ConcreteA } 
class Example[U <: B](resolver: U) 
object Test { 
    new Example(new ConcreteB) 
} 

tip üyelerini kullanarak, bunların arıtma kullanarak tipi parametreleri olarak ortaya edilebileceğini bilmek yararlıdır

, Miles Sabin yanıtında olarak: Why is this cyclic reference with a type projection illegal? a related question Jean-Philippe pelet cevabı ise

yazın çıkarsama tipi parametresini daha yüksek kinded yaparak destekli edildi. Eğer ConcreteB fazladan tipi parametresi tanıtmak , o zaman

abstract class A abstract class B[T <: A] class ConcreteA extends A class ConcreteB[T <: A] extends B[T] class Example[T <: A, U[T0 <: A] <: B[T0]](resolver: U[T]) object Test { new Example(new ConcreteB[ConcreteA]) } 

Scala 2.9 aşağıda gizemli hata mesajı verir, çıkarsama çalışabilir yazın ancak Miles Sabin 2,9 sabit olacak bir hata olduğunu işaret ediyor. 1

<console>:15: error: kinds of the type arguments (ConcreteA,ConcreteB[T0]) do not conform to the expected kinds of the type parameters (type T,type U) in class Example. 
ConcreteB[T0]'s type parameters do not match type U's expected parameters: class ConcreteB has one type parameter, but type U has one 
     new Example(new ConcreteB[ConcreteA]) 
      ^
+1

Aşağıdaki Miles yanıtıyla ilgili devam eden tartışmaya bakın. –

+0

Miles'ın cevabı, kabul edilen cevap haline geldiği için artık yukarıda. – ArtB

2

2.9.1.RC1 ve gövde ile beklendiği gibi aşağıdaki eserler. Ben yararlı buluyorum

Birkaç basit kurallar şunlardır: tip parametrelerin

  • Tipi parametreleri çıkarımda: Scala tür kesmesi sadece parametre listesinde belirtilen türde (karışık olmamaya görür tip parametre listesi ile).

  • Önceki parametreler gelecek parametreleri anlaması için kullanılmaz: Tip bilgiler sadece listeler değil parametreleri boyunca parametreye akar.


Ancak bu özel örnekte tip üyeleri ileriye yolu (teşekkürler @Kipton Barros vardır!

İlgili konular