1
votes

I'm trying to pass high order generic function to another generic function as parameter. However, I am quite unable to make it work. Following is sample code of what I am trying to achieve.

def foo[T](data: Seq[T]) = {
    //some codes 
}

def bar[U](id: Sring, fn: Seq[U] => Unit) = {
    criteria match {
      case x => data:Seq[String] = //some data; 
                fn(data)
      case b => data:Seq[Int] = //some data; 
                fn(data)
      case c => data:Seq[Char] = //some data; 
                fn(data)
    }
}

bar("123", foo)

If I run the code, I will get error - Type mismatch - expected Seq[U] found - Seq[String]

2

2 Answers

2
votes

val data must be of type U, because that is the argument of fn:

def bar[U](id: Sring, fn: Seq[U] => Unit) = {
    val data: Seq[U] = //some data.
    fn(data) //I want U to be type of data i.e. Seq[String]
}

If you want U to be a String, then you must specify it when invoking bar.

bar[String]("123", foo)

This is defined on runtime so you can't decide inside of bar the type it should have. If you want it always to be a String, then simply remove U.

1
votes

It doesn't make sense for bar to be generic while using the specific type String within it. fn is a Seq[U] => Unit, but you're passing it a very specific Seq[String]. fn will only work if U = String. What happens if fn is a Seq[Int] => Unit? The types aren't guaranteed to match.

Since the body of bar expects fn to accept a Seq[String], the only thing you can really do is require fn to be a Seq[String] => Unit.

def foo[T](data: Seq[T]) = data.foreach(println)

def bar(id: String, fn: Seq[String] => Unit) = {
    val data: Seq[String] = List("a", "b", "c")
    fn(data)
}

scala> bar("123", foo)
a
b
c