2012-04-27 11 views
6

Bu sorun yazdığım bir modülde ortaya çıktı, ancak aynı davranışı sergileyen minimal bir durum yaptım.Neden çıkarım yazmıyorsunuz?

class Minimal[T](x : T) { 
    def doSomething = x 
} 

object Sugar { 
    type S[T] = { def doSomething : T } 
    def apply[T, X <: S[T]] (x: X) = x.doSomething 
} 

object Error { 
    val a = new Minimal(4) 
    Sugar(a) // error: inferred [Nothing, Minimal[Int]] does not fit the bounds of apply 
    Sugar[Int, Minimal[Int]](a) // works as expected 
} 

sorun derleyici Minimal (Int) için iç parametre anlamaya yönetir olduğunu, ama açıktır ki apply eşleşmeyen Nothing için T diğer oluşumu, ayarlar. Bunlar, ilk parametrenin kaldırılması, T'nin tanımlanmadığı gibi ikinci bir şikayette bulunduğundan, kesinlikle T aynıdır.

Derleyici, ilk parametreyi bulamadığı veya bu bir hata mı olduğu anlamına gelen bazı belirsizlik var mı? Bu incelikle çalışabilir miyim?

Ek bilgi: Bu kod sözdizimsel şeker girişiminin basit bir örneğidir. Orijinal kod, a modülünü |(a)| yapmak için dener; burada a, bir vektördür. Açıkça |(a)|, |[Float,Vector3[Float]](a)|'u yazmaktan daha iyidir, ancak maalesef bunu daha kolay hale getirmek için unary_| kullanamıyorum.

gerçek hata: yapı tipi üzerinde sınırları ile bir tuhaflık var

inferred type arguments [Nothing,Minimal[Int]] do not conform to method apply's type parameter bounds [T,X <: Sugar.S[T]]

cevap

9

Bu bir Scala derleyici hatası değil, ancak kesinlikle Scala'nın tür çıkarımının bir sınırlamasıdır. Derleyici, X, S[T] adresindeki bağlamayı, X için çözülmeden önce belirlemek ister, ancak sınır, numaralı sınırsız türden bahseder ve bu nedenle Nothing numaralı adrese gider ve buradan devam eder. X tamamen çözümlendikten sonra T yeniden ziyaret edilmiyor ... şu anki tür çıkarımı her zaman bu tür bir durumda soldan sağa ilerler.

senin örneğin doğru gerçek durumu temsil ediyorsa

sonra,

def apply[T](x : S[T]) = x.doSomething 
İşte T

MinimalS[T] doğrudan ziyade bir aracı sınırlı tip değişkeni yoluyla uygun şekilde anlaşılmaktadır edilecek basit bir düzeltme var.

Güncelleme

Yuşa çözüm ayrıca türünü T çıkarım sorununu önler, ama tamamen farklı bir şekilde. (T artık X 'in bağlı olarak bahsedilen olduğu için) için

def apply[T, X <% S[T]](x : X) = x.doSomething 

desugars,

def apply[T, X](x : X)(implicit conv : X => S[T]) = x.doSomething 

tip değişkenler T ve X artık için bağımsız bir şekilde çözülebilir.Bu, X'un hemen Minimal olduğu ve'un örtülü aramanın bir parçası olarak örtülü aramanın bir parçası olarak, conv örtük bağımsız değişkenini karşılamak için 10 değerini çözmesi anlamına gelir. scala.Predef numaralı belgede conforms, bu formun değerlerini üretir ve bağlamda, Minimal, T türünde bir argümanın Int. Bunu Scala'da functional dependencies örneğinde görebilirsiniz.

+0

Evet, bu çözüm benim durumumda iyi çalışıyor. Aynı zamanda Joshua'nın çözümünden de daha temizdir (üzgünüm Yeşim!). Joshua'nın çözümünün neden işe yarayacağını anlatabilir misin? – Dylan

+0

Joshua'nın çözümünün neden işe yarayıp yaramadığına dair bir açıklama vermek üzere güncellendi. –

4

, S yerine [T] ile bağlanmış bir görünümünü kullanmak.

def apply[T, X <% S[T]] (x: X) = x.doSomething iyi çalışıyor.

+1

Harika, bu işe yarıyor ama kesinlikle yaklaşımlar arasında fark olmamalı? Bu durumda görüş almak sadece bir süper sınıfa gidiyor, değil mi? Bu, bu düzeltmenin derleyicideki bir hata için bir geçici çözüm olduğu anlamına mı geliyor? – Dylan

+0

Ah, şimdi anlıyorum, 'S' bir üst sınıf değil - sadece bir bakış (bir anlamda). Bu nedenle, çoğu durumda gerekli olmamasına rağmen, bir görünüm bağlı daha uygundur. – Dylan

İlgili konular