Jacek Laskowski
Jacek Laskowski

Reputation: 74669

Can a function literal use type parameter in Scala?

Given the following definition of a method removeAt that's polymorphic:

def removeAt[T](n: Int, ts: Seq[T]): (Seq[T], T) = ???

How can I declare a list of removeAt-like functions? Can a function literal use type parameter?

How can I make the following compilable and able to contain removeAt?

List[(Int, Seq[_]) => (Seq[_], _)](removeAt)

UPDATE: Why does the following work fine so I can foreach over the list and execute the functions? That's exactly what I needed in the first place.

val solutions = Seq[(Int, Seq[Any]) => (Seq[Any], Any)](
  removeAt
)

Upvotes: 6

Views: 711

Answers (5)

goral
goral

Reputation: 1265

Does this help you?

val removeAt: Int => Seq[_] => (Seq[_], _) = n => seq => (seq, seq(n))

val listOfRemoveFun = List[(Int => Seq[_] => (Seq[_], _))](removeAt)

listOfRemoveFun.foreach(fun => println(fun(1)(Seq(1,2,3))))   //(List(1, 2, 3),2)

Upvotes: 0

DaunnC
DaunnC

Reputation: 1301

Ok, so we have a polymorphic function (only example to try and to compile, using shapeless):

def removeAt[T](n: Int, ts: Seq[T]): (Seq[T], T) = ...

Let's define a HList of these functions:

val mapList = 
    removeAt[Int] _     ::
    removeAt[String] _  ::
    removeAt[Boolean] _ :: HNil

So it is possible, to take any of these functions and to apply it.

Due to your example after update: In fact, you lose all information about polymorphic function types (due to type erasure). All functions in your list gonna have (Int, Seq[Any]) => (Seq[Any], Any) type, it is not good, as I recognize.

So with common lists, you can make the same (you should write type parameter), but also, you will lose all inforamtion about functions type, and in fact it is pointless to make such list or seq.

Upvotes: 0

DaoWen
DaoWen

Reputation: 33019

You might be asking something more general than this, but for the above problem I feel like you're just approaching it wrong. If I were you, I'd extend Seq to support the removeAt method using an implicit value class. Here's an example that would add the removeAt method:

implicit class MoreSeqOps[T](val seq: Seq[T]) extends AnyVal {
  def removeAt(n: Int): (Seq[T], T) = {
    val (xs, ys) = seq.splitAt(n)
    return (xs ++ ys.tail, ys.head)
  }
}

By using a value class, you avoid the extra overhead associated with creating a wrapper instance. Here's a sample usage from the REPL:

scala> (1 to 10) removeAt 3
res7: (Seq[Int], Int) = (Vector(1, 2, 3, 5, 6, 7, 8, 9, 10),4)

Upvotes: 0

Jacek Laskowski
Jacek Laskowski

Reputation: 74669

The blog post First-class polymorphic function values in shapeless (1 of 3) — Function values in Scala seems to imply that there's no way in "standard" Scala to have polymorphic function values:

We can have first-class monomorphic function values and we can have second-class polymorphic methods, but we can't have first-class polymorphic function values ... at least we can't with the standard Scala definitions.

It looks like we need a library like shapeless.

Upvotes: 6

Good enough to make the container carry these functions would be to use bottom types for example:

val f = removeAt _ 

var l: List[(Int, Seq[Nothing]) => (Seq[Nothing], Nothing)] = Nil
l = f :: l

I've explained them in this article for example: http://ktoso.github.io/scala-types-of-types/#the-bottom-types-nothing-and-null

Upvotes: 0

Related Questions