Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a function have a polymorphic return type based on the type argument of its type parameter?

I have some code like this:

sealed trait Foo[A] {
  def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]

I'd like to have a function which can use the A type given a subtype's type parameter.

// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)

I can't figure out how to declare dostuff in a way that works. The closest thing I can figure out is

def dostuff[B <: Foo[A]](p: Param): A

But that doesn't work because A is undefined in that position. I can do something like

def dostuff[A, B <: Foo[A]](p: Param): A

But then I have to invoke it like dostuff[String, StringFoo](param) which is pretty ugly.

It seems like the compiler should have all the information it needs to move A across to the return type, how can I make this work, either in standard scala or with a library. I'm on scala 2.10 currently if that impacts the answer. I'm open to a 2.11-only solution if it's possible there but impossible in 2.10

like image 670
Daenyth Avatar asked Apr 10 '15 19:04

Daenyth


People also ask

What are polymorphic functions?

A function that can evaluate to or be applied to values of different types is known as a polymorphic function. A data type that can appear to be of a generalized type (e.g. a list with elements of arbitrary type) is designated polymorphic data type like the generalized type from which such specializations are made.

What is return type in polymorphism?

Edit: By return type polymorphism I mean overloading the function signature only in the return type. For example, C++ and Java only allow overloading in the type of the formal parameters, not in the return type.

What do you call a Scala method that is parametrized by type as well as by value?

Language. Methods in Scala can be parameterized by type as well as by value. The syntax is similar to that of generic classes. Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses.

What is polymorphism in Scala?

Polymorphism is the ability of any data to be processed in more than one form. The word itself indicates the meaning as means many and. means types. Scala implements polymorphism through virtual functions, overloaded functions and overloaded operators.


1 Answers

Another option is to use type members:

sealed trait Foo {
  type Value
  def value: Value
}

case class StringFoo(value: String) extends Foo { type Value = String }
case class IntFoo(value: Int) extends Foo { type Value = Int }

def dostuff[B <: Foo](p: Any): B#Value = ???

// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)

Note that both solutions mainly work around the syntactic restriction in Scala, that you cannot fix one type parameter of a list and have the compiler infer the other.

like image 160
gzm0 Avatar answered Oct 09 '22 09:10

gzm0