2016-10-12 16 views
0

В следующей функции, компилятор Scala способен определить тип возвращаемого значения к наименьшему общему надтипа значений, используемых в если/другое выражение:Определить общие нижние границы параметров

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.

Однако, если A и B являются параметры типа в определении функции 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

Если вам не нужны типы Exacta аргументов, то следующее будет обычно достаточно:

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

Scala автоматически базовый тип типов аргументов их верхней границе (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 

Здесь A и B точные типы аргументов, и C их LUB. C имеет ограничение быть супертипом A: C >: A, но он также должен быть типом второго аргумента, так как он определен как f: B with C, и поэтому он определяется как LUB A и B.

Мы можем проверить правильность вывода типа с этим определением со следующим кодом:

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

Вы можете применять верхние оценки типа А и В, если вы знаете, 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 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^