2013-06-25 30 views
2

我一直在努力尋找一種方法來處理以下情況,我希望找到一個統一類型參數的公共視圖(或超類),以便可以訪問類型類相比較蘋果和蘋果:在類中統一視圖邊界

case class Foo[A](i:A) { 
    def cmp[B:Ordering, C <% B](b:B)(implicit ev: A => B) = implicitly[Ordering[B]].lt(i,b) 
} 
// Foo(1).cmp(2.0) works 
// Foo(1.0).cmp(2) complains about evidence of Double => Int 

現在,這可以平凡與簡單的函數來完成:

def cmp[A:Ordering](a1:A, a2:A) = implicitly[Ordering[A]].lt(a1,a2) 
// cmp(Foo(1).a, 1.0) 
// cmp(Foo(1.0).a, 1) 

不過,我希望它作爲生活的富的方法。關於我能做些什麼來強迫它使用視圖邊界的想法?

回答

1

你可以依賴一個類型類。有點重,但工作原理:

trait Cmp[A,B] { 
    def cmp(a: A, b: B): Boolean 
} 
trait LowPriorityCmpImplicits { 
    implicit def cmp1[A,B](implicit conv: A => B, ord: Ordering[B]) = new Cmp[A, B]{ 
    def cmp(a: A, b: B) = ord.lt(conv(a), b) 
    } 
} 
object Cmp extends LowPriorityCmpImplicits { 
    implicit def cmp2[A,B](implicit conv: B => A, ord: Ordering[A]) = new Cmp[A, B]{ 
    def cmp(a: A, b: B) = ord.lt(a, conv(b)) 
    } 
} 

case class Foo[A](i:A) { 
    def cmp[B](b: B)(implicit cmp: Cmp[A,B]) = cmp.cmp(i, b) 
} 

LowPriorityCmpImplicits特點是爲了避免歧義,當這兩種類型相同(cmp2將優於cmp1) 測試:

scala> Foo(1).cmp(2.0) 
res0: Boolean = true 
scala> Foo(1.0).cmp(2) 
res1: Boolean = true 
scala> Foo(1).cmp(2) 
res2: Boolean = true 
scala> Foo(2).cmp(1.0) 
res3: Boolean = false 
scala> Foo(2.0).cmp(1) 
res4: Boolean = false 
scala> Foo(2).cmp(1) 
res5: Boolean = false 
+0

這是一個非常合理的工作解決我的問題。想知道爲什麼編譯器會遇到這種問題?嘗試處理數字和常規類時,這很不幸很常見。 – Refefer