2016-10-12 45 views
0

在下面的函数共同下界,Scala编译器能够定义的返回类型以在如果/ else表达式中使用的值的最低的共同父类型:定义的参数

def cond(b: Boolean, t: A, f: B) = if (b) t else f 

考虑以下层次结构:

class X 
class A extends X 
class B extends X 

上述函数cond被定义为返回X类型的值。

但是,如果AB都在cond函数的定义类型的参数,它的返回类型为Any

def cond[A, B](b: Boolean, t: A, f: B) = if (b) t else f 

是否有可能使编译器使用类型的最低共同父参数?

我尝试以下的一些变型中,没有成功:

def cond[A, B, R >: A with B](b: Boolean, t: A, f: B): R = if (b) t else f 
def cond[A, B, R](b: Boolean, t: A, f: B)(implicit ev1: A <:< R, ev2: B <:< R): R = if (b) t else f 

EDIT:上面的问题是过分简化。其实我真正的问题就已经解决了类型参数之一:

class C[A](b: Boolean, t: A) { 
    def cond[B](f: B) = if(b) t else f 
} 

回答

1

如果你不需要正序连赢类型的参数,那么下面通常就足够了:

def cond[T](b: Boolean, t: T, f: T) = if (b) t else f 

斯卡拉将自动上溯造型的类型参数的最小上界(LUB ):

scala> cond(true, new A, new B) 
res0: X = [email protected] 

但是如果你需要的确切类型,例如隐式的决定,我倍儿ieve以下伎俩应工作:

def cond[A, B, C >: A](b: Boolean, t: A, f: B with C): C = if (b) t else f 

这里AB是准确的参数类型,以及C是他们的LUB。 C约束为超类型AC >: A,但它也应该是第二个参数的类型,因为它被定义为f: B with C,因此它被推断为AB的LUB。

我们可以检查正确的类型推断这一定义与下面的代码:

import reflect.runtime.universe._ 
def cond[A, B, C >: A](b: Boolean, t: A, f: B with C)(
    implicit ta: TypeTag[A], 
      tb: TypeTag[B], 
      tc: TypeTag[C] 
): C = { 
    println(ta) 
    println(tb) 
    println(tc) 
    if (b) t else f 
} 

scala> cond(true, new A, new B) 
TypeTag[A] 
TypeTag[B] 
TypeTag[X] 
res5: X = [email protected] 
1

你可以申请上界类型A和B,如果你知道LUB静态。

def cond[A <: C, B <: C,C](b: Boolean, t: A, f: B) = if (b) t else f 
0

感谢@nikhil和@Kolmar答案我可以想出这种解决方案:

class C[A](b: Boolean, t: A) { 
    def cond[B <: R, R >: A](f: B): R = if(b) t else f 
}