Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write a method in Scala returning objects with different type parameter?

Is it possible to write a method in Scala which returns an object of a type-parameterized class with different type paramter ? Something like this:

class A[T]

def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]

Please note: The Code above is fictional to show the type of problem; The code above does not make semantically sense.

The code above will not compile because return type A is not parameterized.

like image 459
John Threepwood Avatar asked Mar 27 '26 15:03

John Threepwood


2 Answers

You can, and you can even do it with type-safety with the aid of implicit arguments that encapsulate the pairings:

class TypeMapping[+A,B] {
  def newListB = List.empty[B]
}
trait Logical
object True extends Logical
object False extends Logical

implicit val mapFalseToInt = new TypeMapping[False.type,Int]
implicit val mapTrueToString = new TypeMapping[True.type,String]

def f[A <: Logical,B](switch: A)(implicit tmap: TypeMapping[A,B]) = tmap.newListB

scala> f(True)
res2: List[String] = List()

scala> f(False)
res3: List[Int] = List()

You do have to explicitly map from boolean values to the custom True and False values.

(I have chosen List as the target class just as an example; you could pick anything or even make it generic with a little more work.)

(Edit: as oxbow_lakes points out, if you need all possible return values to be represented on the same code path, then this alone won't do it, because the superclass of List[Int] and List[String] is List[Any], which isn't much help. In that case, you should use an Either. My solution is for a single function that will be used only in the True or False contexts, and can maintain the type information there.)

like image 155
Rex Kerr Avatar answered Mar 29 '26 08:03

Rex Kerr


One way of expressing this would be by using Either;

def f(switch: Boolean) = if (switch) Left(new A[Int]) else Right(newA[String])

This of course returns an Either[A[Int], A[String]]. You certainly cannot (at the moment) declare a method which returns some parameterized type P, with some subset of type parameters (i.e. only Int or String).

The language ceylon has union types and I understand the intention is to add these to scala in the near future, in which case, you could define a method:

def f(switch: Boolean): A[Int|String] = ...
like image 35
oxbow_lakes Avatar answered Mar 29 '26 08:03

oxbow_lakes