2011-10-29 35 views
6
scala> implicit def transitive[A, B, C](implicit f: A => B, g: B => C): A => C = f andThen g 
transitive: [A, B, C](implicit f: A => B, implicit g: B => C)A => C 

scala> class Foo; class Bar; class Baz { def lol = println("lol") } 
defined class Foo 
defined class Bar 
defined class Baz 

scala> implicit def foo2Bar(f: Foo) = new Bar 
foo2Bar: (f: Foo)Bar 

scala> implicit def bar2Baz(f: Bar) = new Baz 
bar2Baz: (f: Bar)Baz 

scala> implicitly[Foo => Baz] 
<console>:14: error: diverging implicit expansion for type Foo => Baz 
starting with method transitive in object $iw 
       implicitly[Foo => Baz] 

Yukarıdaki koddan açıkça anlaşılacağı gibi, kapsam içine alındığında örtülü dönüşümleri geçişli yapacak bir yöntem yazmaya çalışıyorum. Bu kodu çalışmak için bekliyordum, ama şaşırtıcı değil. Yukarıdaki hata mesajı nedir ve bu kodu nasıl çalıştırabilirim?İçindekilerle ilgili meraklı hata iletisi

cevap

4

Güncelleme: açıklamalarda belirtildiği gibi, bu yaklaşım 2.8 üzerinde derlemek etmez ve implicitly[Foo => Baz] düzgün çalışırken, (new Foo).lol yapmaz.

implicit def conforms[A, B, C](implicit f: A => B, g: B => C): A => C = f andThen g 

fazla ayrıntı için this answer bakınız: Reklam transitiveconforms için Predef yöntemini gölge adlandırmak eğer


Bu sadece iyi çalışır. Bir yan not olarak


: -Xlog-implicits ile Çoğaltma başlayan bu gibi durumlarda daha bilgilendirici hata iletileri almak için kullanışlı bir yoldur.

scala> implicitly[Foo => Baz] 
scala.this.Predef.conforms is not a valid implicit value for Foo => Baz because: 
type mismatch; 
found : <:<[Foo,Foo] 
required: Foo => Baz 
<console>:14: error: diverging implicit expansion for type Foo => Baz 
starting with method transitive in object $iw 
       implicitly[Foo => Baz] 
         ^
scala.this.Predef.conforms is not a valid implicit value for Foo => Baz because: 
type mismatch; 
found : <:<[Foo,Foo] 
required: Foo => Baz 
transitive is not a valid implicit value for Unit => Foo => Baz because: 
not enough arguments for method transitive: (implicit f: A => B, implicit g: B => C)A => C. 
Unspecified value parameter g. 
transitive is not a valid implicit value for => Unit => Foo => Baz because: 
not enough arguments for method transitive: (implicit f: A => B, implicit g: B => C)A => C. 
Unspecified value parameter g. 

Ama biz geçici fonksiyonları olmak foo2Bar ve bar2Baz yeniden eğer, belirsizlik vurgulamaktadır bir hata mesajı alıyorum: Bu durumda yardımcı bir çok ilk de değil Şimdi

implicit val foo2Bar = (_: Foo) => new Bar 
implicit val bar2Baz = (_: Bar) => new Baz 

scala> implicitly[Foo => Baz] 
transitive is not a valid implicit value for Foo => Baz because: 
ambiguous implicit values: 
both method conforms in object Predef of type [A]=> <:<[A,A] 
and value foo2Bar in object $iw of type => Foo => Bar 
match expected type Foo => B 

öyle Sadece conforms numaralı gölgeye ihtiyaç duyduğumuzu netleştirin.

+0

Teşekkürler Travis, ama önerdiğiniz gibi yeniden adlandırdıktan sonra hala benim için çalışmıyor. http://ideone.com/KV0aY – missingfaktor

+0

@missingfaktor: Benim için 2.9.1'de çalışıyor. 2.8'e bir göz atacağım. –

+0

2.9.1'de test ettim. İfade, örtülü olarak [Foo => Baz] çalışır, ancak '(yeni Foo) .ol' değildir. – missingfaktor