2017-03-09 57 views
1

我试图将高阶泛型函数作为参数传递给另一个泛型函数。但是,我很难做到这一点。以下是我试图实现的示例代码。当传递高阶函数作为参数时,Scala泛型 - 类型不匹配错误

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) 

如果我运行代码,我会得到错误 - 类型不匹配 - 预计序列[U]发现 - 序列[字符串]

回答

2

val data必须是U类型的,因为那是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] 
} 

如果你想U成为String,然后调用bar时,必须指定它。

bar[String]("123", foo) 

这是在运行时定义的,所以你不能的bar它应该有类型内决定。如果你想要它总是一个字符串,那么只需删除U

+0

如果bar()动态调用fn()会怎么样?即可以根据条件将foo()例如不同的数据类型序列通过。 Seq [String],Seq [Int],Seq [Char]等,因为我已经更新了问题。 –

+0

@RaKa这是一个完全不同的问题。你需要一个classtag:http://stackoverflow.com/questions/5400394/how-to-get-the-actual-type-of-a-generic-type你实际上想要实现什么?在我看来,如果没有泛型,你的代码可以大大简化 – nmat

1

它没有意义bar是通用,同时使用其中的特定类型Stringfn是一个Seq[U] => Unit,但您传递给它一个非常具体的Seq[String]fn只适用于U = String。如果fnSeq[Int] => Unit,会发生什么情况?这些类型不能保证匹配。

由于bar体预计fn接受Seq[String],你所能做到的要求fn是一个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 
+0

如果bar()用多种不同的数据类型调用fn()会怎么样。例如正如你所说的Seq [Int]?我们可以这样做吗?因为,我在bar函数中有匹配条件,它根据条件生成不同的数据类型序列并调用fn()。 –