Reputation: 74669
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
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
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
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
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
Reputation: 13130
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