2016-10-12 11 views
0

In der folgenden Funktion wird der Scala Compiler der Lage, den Rückgabetyp auf den kleinsten gemeinsamen geordneter Typ der Werte in den if/else Ausdruck verwendet, um zu definieren:definieren gemeinsame untere Grenzen von Parametern

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

Berücksichtigung der folgenden Hierarchie:

class X 
class A extends X 
class B extends X 

die Funktion cond oben als zurückkehr einen Wert vom Typ X definiert ist.

Wenn jedoch A und B Typ Parameter in der Definition der cond Funktion sind, ist deren Rückgabetyp Any:

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

Ist es möglich, den Compiler zu machen, den kleinsten gemeinsamen Supertyp des Typs verwenden Parameter?

Ich habe versucht, einige Varianten der folgenden, ohne Erfolg:

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: Die Frage oben zu stark vereinfacht wird. In der Tat hatte mein eigentliches Problem einer der Parameter des Typs bereits gelöst:

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

Antwort

1

Wenn Sie die Exakta-Typen der Argumente nicht benötigen, dann wird die folgende Regel genügen:

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

Scala automatisch die Typen der Argumente, um ihre obere Grenze upCast wird (LUB):

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

Aber wenn Sie die genauen Typen benötigen, beispielsweise für die implizite Auflösung, I bel IEVE der folgende Trick funktionieren sollte:

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

Hier A und B sind genaue Typen der Argumente und C ist ihre LUB. C hat die Einschränkung, die Obertyp von A: C >: A zu sein, aber es sollte auch der Typ des zweiten Arguments sein, da es als f: B with C definiert ist, und somit wird es als die LUB von A und B abgeleitet.

Wir können richtig Typinferenz überprüfen Sie mit dieser Definition mit dem folgenden Code:

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

Sie können oberen Typ Grenzen A und B gelten, wenn Sie LUB statisch wissen.

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

Dank Antworten auf @nikhil und @Kolmar Ich konnte zu dieser Lösung kommen:

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