2013-10-17 104 views
4

我知道Scala中不支持「聯合類型」,但交集類型又如何呢?Scala中的「交集類型」

總之,我想這樣的功能:

def intersect[A,B,C](a: A, b: B): C = ??? // a & b 

或方法:

class A { 
    def intersect[B, C](b: B): C = ??? // this & b 
} 

AB共用一個超保證了交叉操作的有效性,並C將是在AB的交叉點處的類型。

在我的用例中,A或B表示變量或常量(同一類型)。我想從單變量域的變量中區分出一個常量。如果我嘗試與一個值相交,我返回值(或者返回空集/拋出異常,如果該值不在集中)。

這裏是期望輸出的一個例子:

trait IntExpression { 
    // Correct signature to be determined 
    def intersect [A <: IntExpression, B <: A & this.type] (that: A): B 
} 
case class IntVariable(domain: Seq[Int]) extends IntExpression 
case class IntConstant(value: Int) extends IntExpression 

val a = IntVariable(1,2,3) 
val b = IntVariable(2,3,4) 
val c = IntConstant(2) 

然後:

a intersect b == b intersect a == IntVariable(2,3) 
a intersect c == c intersect a == IntConstant(2) 
+0

可能您可以編寫一個派生此類集的宏嗎?只要它有權訪問類層次結構,它應該是可能的。 – Ashalynd

+0

我不太明白你期望的輸出。你能舉一個可能的輸入值和預期輸出的例子嗎? – drexin

+0

我沒有看到這個用例。你爲什麼不使用套件? – drexin

回答

0

我用++的實現,因爲它的存在。 Set上的intersect不起作用,因爲Set是不變的。如果這沒有意義,請忽略它。

def intersect[C, A <: C, B <: C](as: Seq[A], bs: Seq[B]): Seq[C] = as ++ bs 
+0

這是錯誤的。 '相交(Seq(1,2,3),Seq(2,3,4))== Seq(1,2,3,2,3,4)'該操作正在尋找'Seq(2 ,3)' –

+1

我的答案只是讓類型正確。 – ziggystar

2

作爲ziggystar正確如上所述:A & B是Scala A with B

關於您想在運行時創建伴隨類型C的事實,您必須根據您在AB中獲得的類型在運行時創建此類型。

解決方案,或至少一個線索,你可能會發現在How to mix-in a trait to instance?

但是,您在使用情況下想要的是http://en.wikipedia.org/wiki/Dependent_type的情況。儘管在Scala中不支持依賴類型,但您可能總是嘗試使用Agda;)