2013-10-17 66 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;)