2009-07-26 28 views
8

Birbirine bağlı olmak üzere tasarlanmış iki sınıfım var, Input ve Output. Output, bazı türlerde değerler üretir ve Input bunları tüketir.Scala bu örnekte neden parametre kullanamıyor?

class Input[T] { 
    var output: Option[Output[_ <: T]] = None 
} 
class Output[T] { 
    var input: Option[Input[_ >: T]] = None 
} 

bir Input ve Output çifti sürece Input tür parametresi Output tip parametrenin bir üst tip olarak değerinin aynı tür üzerinde işlem yoksa sorun değil. Her iki sınıftaki tür parametresinin değişmez olduğunu unutmayın; Gerçek versiyonlarda hem ko- hem de kontravaryant pozisyonlarda kullanılır.

val out = new Output[String] 
val in = new Input[AnyRef] 
connect(out, in) 

: Ben aşağıda bu yöntemi çağırırsanız, bir tür hatası aldığınız

def connect[T](output: Output[T], input: Input[_ >: T]) = { 
    output.input = Some(input) 
    input.output = Some(output) 
} 

:

Bir Input/ Output çifti arasında bir bağlantı kurar başka yerde bir connect yöntemine sahip Hata:

test.scala:17: error: type mismatch; 
found : Output[String] 
required: Output[AnyRef] 
    connect(out, in) 
     ^

Yapabilirim Bunu tür parametresi yazarak çöz (bu durumda, connect[String] yazabilirim, ama derleyicinin bunu benim için çözmesi gerektiğini düşünüyorum). Tür parametresi otomatik olarak çıkacak şekilde connect yöntemini nasıl değiştirebilirim?


Düzenleme: Şimdilik, ben connectOutput bir yöntem bu yüzden türü parametresi otomatik alır hale getirdik. Bu aynı zamanda out connect in infix notasyonunu kullanabileceğim ek faydaya sahiptir, ancak tasarım biraz garip geliyor.

Derleyicinin bu davranışı neden sergilediğini hala merak ediyorum. Tip parametresini çıkarabilmeli gibi hissediyorum. Bu aslında belirtilen şekilde çalışıyor mu?

+0

"Aynı türde bir değer kullanmayın" * –

+0

sorusunu Scala posta listesine sormayı denediniz mi? – GClaramunt

cevap

6

Bazen birden çok parametre listelerini kullanırsanız daha iyi sonuçlar alırsınız: Bu durumda gerçekten

def connect[T](output: Output[T])(input: Input[_ >: T]) = { 
    output.input = Some(input) 
    input.output = Some(output) 
} 

connect(out)(in) 

... ve işe yarıyor.

+3

Bunun nedenini genişletebilir misiniz? * "bazen daha iyi sonuçlar elde edin" * çok belirleyici gelmiyor! –

+6

Ne yazýk ki, yazýcý yazýcý yazýlmýþtýr, bazen de belirleyici deðildir. –

0

Tamamen yanlış olabilirsiniz, ancak sorunun giriş ve çıkışları bir araya getirdiğinizde sorun olduğunu düşünüyorum: girişinin bir T alt türüyle sınırlı bir çıkışı vardır, ancak çıktının bir üst türüyle sınırlı bir girişi vardır. T, her iki koşulu karşılayabilecek tek tip T.Çıktının (ile yer değiştirilir _ <: T) ile bir girdi oluşturduğu zaman

Input[T] -> Output[ _ <: T ] 
Output[Q] -> Input[ _ >: Q ] 

olsun:

Input[T]->Input[ _ >: [_ <: T] ] 

aynı

Giriş [T] ile -> Giriş [_ < T <: _] Bu nedenle

tür uyumsuzluğu

+0

Örneğimde String ve AnyRef kısıtlarımı tatmin ediyor. Çıktı, Dizeler üretir ve bazı String öğesinin üst düzeyini tüketen bir Giriş gerektirir. Girdi, AnyRef'leri tüketir ve AnyRef'in bazı alt türlerini üreten bir Çıkış gerektirir. String, AnyRef'in bir alt türü olduğu için, kısıtlamalar karşılanır. –

+0

Sorun, bağlantı için tam olarak uygun bir tür parametre olduğu ve bu da Çıktının type parametresidir. Bunu açıkça belirttiğimde, iyi çalışıyor. Yapmazsam, Girdi'nin type parametresini kullanmaya çalışır ve Output argümanı için bir tip hatası alırım. –

+0

Üzgünüz, [T] bağlantısının imzasındaki [_>: T] girişini yanlış okudum ( – GClaramunt

0

Aslında scala tipi inferene şimdilik "tekrarlama" işlemez. Bu nedenle, argüman türü yalnızca başka argüman scala ile birlikte sıralamada çıkarılabilirse, çıkarımda başarısız olur. Ama eğer farklı argüman listesi kullanırsanız scala f(a)(b)(c,d), liste türlerini listeden çıkarır, bu yüzden daha iyi çalışır.

PS Çok basitleştirilmiş, ancak size bazı ipuçları verebilir.

İlgili konular