2013-06-24 20 views
5

benim gerçek problemin basitleştirilmiş versiyonu aşağıdadır:Scala: Örtülü parametresinde hata

class Z[T] 
object E extends Enumeration { 
    implicit val z = new Z[Value] 
    val X, Y = Value 
} 
implicit def f[T : Z] = (getter: T) => 0 
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0 
def e: Option[E.Value] = null 
val b: Int = e 

Bu örtük o (e) dönüştürüldü b, çalışır (f (E.z)). Ancak küçük değişikliklerle şu: o kadar manuel açık dönüşüm (e) (f (E.z)) hala çalışır iken orijinal koddan özde bir fark olmamasına rağmen

implicit def f[T : Z] = (setter: T => Unit) => 0 
implicit def o[T](v: Option[T])(implicit toInt: (T => Unit) => Int) = 0 

uygun örtülü değer E.z bulmakta başarısız.

Ben örtük parametrenin uygulanması henüz tamamlanmadı ve çözülmemiş bir çok sorununun hala vardır biliyorum. Bu onlardan biri ise, Scala katılımcılarına bildirmek isterim. Yani sorum şu, a) bu gerçekten bir böcek mi? b) öyleyse, nerede ve nasıl bir hata oluşturabilirim ki gelecekte düzeltilebilir mi?

GÜNCELLEME

Travis'in cevabı bir cazibe gibi çalıştı! Bu arada, kod yukarıda benim orijinal probleme bir çözüm oldu: Bu kodu

implicit object E extends Enumeration { val X, Y = Value } 
implicit object F extends Enumeration { val X, Y = Value } 
implicit def f[T <: Enumeration](getter: T#Value)(implicit e: T) = 0 
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0 
val b: Int = Some[E.Value](null) 

durum tersi oldu: setter sürümü ile çalışır ancak daha basit alıcı versiyonuyla. Derleyici, F'yi kullanmanın F'yi aslında derlemediğini ve mantıklı olmadığını, örtük parametresi olarak E'nin veya F'nin kullanılıp kullanılmayacağının karıştırılmasından şikayetçidir.

implicit def f[S <% T => T, T <: Enumeration](getter: T#Value)(implicit e: T) = 0 

Bu çalışır ve ben bir şekilde bu çalışma her ne kadar, hala bu sihirli arkasındaki mantığı anlamıyorum: Ben benzer bir şeyi yaparak çalışan başardı.

+0

İlginç. [Z T] 'E.Value'' olarak anlaşılmaktadır değildir '-Xlog-implicits' ile çalışır, f 'içinde,' t 'görülmektedir. 'Val: b: Bu nedenle bu çalışır ([E.Value] f) Int = O (e) 'fakat bu değildir:' val b: Int = o (e) (f)' '. – gourlaysama

cevap

6

Sen Scala'nın tür kesmesi sisteminin this limitation, bir başka varyasyonu çalıştırmak.

derleyici o E.Value => Unit bir dönüşüm istiyor ikincide f için T o Int için düz eski E.Value bir örtük dönüştürme arıyor İlk durumda, eğer çözmek, ama olmaz (yani Function1[E.Value, Unit]) Int.

Neyse gibi durumlarda kolay bir çözüm bulunmamaktadır bu-sadece bağlı bir görünümü kullanmak:

implicit def f[F <% T => Unit, T: Z] = (setter: F) => 0 

Bu gibi bir şey için desugar olur:

implicit def f[F, T](implicit st: F <:< (T => Unit), ev: Z[T]) = (setter: F) => 0 

derleyici bir dönüşüm istiyor Şimdi ne zaman Int için E.Value => Unit den hemen sonra T E.Value için E.Value => Unit için F çözmek mümkün olacak.

+0

Cevabınız için teşekkürler, bir cazibe gibi çalıştı! Ama hala bu sihrin nasıl çalıştığını anlamıyorum. Yukarıdaki güncellemeye bir göz atabilir ve bir açıklama yapabilir misiniz? Görünüşe göre, S'nin tür çıkarsama sisteminin çalışması için mantıklı olması gerekmiyor. Gizemli. –