Одна вещь, которую вы можете сделать, это изменить ваше определение /
на следующее:
def /[U >: T](f: => U) = o getOrElse f
Это не работает как обычный if
(где тип вывода будет Double
)- вы получаете AnyVal
, но это уже улучшение с очень маленькой модификацией вашего кода.
Обновление: Я думаю, что нашел (немного более сложный) способ сделатьон ведет себя больше как нормальный, если (например, в этом случае, выводя Double
).Попробуйте этот код:
implicit def boolToTernary(cond: Boolean) = new {
def ?[T](f: => T) = if (cond) Ternary(Some(f))
else Ternary[T](None)
}
case class Ternary[T](val o: Option[T]) {
def /[U, That](f: => U)(implicit conv: BiConverter[T, U, That]): That = o map conv.toThat1 getOrElse (conv toThat2 f)
}
class BiConverter[T, U, That](val toThat1: T => That, val toThat2: U => That)
trait LowPriorityBiConverterImplicits {
implicit def subtype[A, T <: A, U <: A]: BiConverter[T, U, A] = new BiConverter[T, U, A](identity[T], identity[U])
}
object BiConverter extends LowPriorityBiConverterImplicits {
implicit def identityConverter[T]: BiConverter[T, T, T] = new BiConverter[T, T, T](identity, identity)
implicit def firstAsSecond[T, U](implicit conv: T => U): BiConverter[T, U, U] = new BiConverter[T, U, U](conv, identity)
implicit def secondAsFirst[T, U](implicit conv: U => T): BiConverter[T, U, T] = new BiConverter[T, U, T](identity, conv)
}
Затем (пример кода):
abstract class Fruit
class Apple extends Fruit
class Banana extends Fruit
def main(args: Array[String]) {
val int = (1 > 2) ? 5 / 6 // Int is inferred
val fruit = (1 > 2) ? new Apple / new Banana // Fruit is inferred
val double1 = (1 > 2) ? 5 / 5.5 // Double is inferred
val double2 = (1 > 2) ? 5.5 / 5 // Double is inferred
}