2011-12-22 61 views
3

我在学习scala,这个问题可能很愚蠢,但是......为什么?scala:type mismatch error - found T,required字符串

例如,这是确定的:

def matchList(ls: List[Int]): List[Int] = ls match { 
    case 1 :: rest => rest 
    case a :: b :: rest => (a + b) :: rest 
    case _ => ls 
} 

matchList: (ls: List[Int])List[Int] 

但随着类型参数的函数不能编译:

def matchList[T](ls: List[T]): List[T] = ls match { 
    case 1 :: rest => rest 
    case a :: b :: rest => (a + b) :: rest 
    case _ => ls 
} 

<console>:10: error: type mismatch; 
found : T 
required: String 
    case a :: b :: rest => (a + b) :: rest 

为什么?

回答

8

对于任何类型的T操作T + T没有任何意义。 (请在所有类型的支持+?想想号加两个狗或两个员工。)

在你的情况,字符串连接运算符是越来越调用(通过any2stringadd皮条客加入),其返回类型为(显然)String。因此错误信息。

你需要的是指定类型T必须支持的操作,你结合T两个值,产生T类型的新价值方式。ScalazSemigroup完美符合法案。

以下工作:

def matchList[T : Semigroup](ls: List[T]): List[T] = ls match { 
    case 1 :: rest => rest 
    case a :: b :: rest => (a |+| b) :: rest // |+| is a generic 'combining' operator 
    case _ => ls 
} 
+0

他是否一定希望手术是联想? – huitseeker 2011-12-22 21:19:47

+0

他没有具体说明。而且我不能想到结合性会伤害他的问题的情况。 – missingfaktor 2011-12-23 04:27:23

+0

你是对的,它不会:'matchList'组合最多两个元素,所以关联性是无关紧要的。 “这只是一个提醒,Semigroup的规格比'T - > T - > T'类型的规格要小。 :) – huitseeker 2011-12-23 05:52:43

3

我认为问题出在(a + b)+运营商的唯一普遍使用的是字符串连接,所以ab必须都以字符串(或自动转换为字符串)为有效。您的参数化类型T未知是字符串,因此无法编译。

+1

@迷茫妖:有一个'斯卡拉any2string'隐含其诱导这种转换案件。在特定的'Int'情况下不需要隐式转换。 – Debilski 2011-12-22 20:57:00

+0

@ confused-demon这里的麻烦在于Scala没有办法知道'T'将会是'Int',所以它不能工作。 – nonVirtualThunk 2011-12-22 21:00:23

+0

对不起,我还没有那么深。 'any2string implicit'是否意味着'如果type在这种情况下是未知的,它将被转换为string'?而且,要完成这个类型的参数化函数,可以如何使用Int,Double和String来实现? – dmitry 2011-12-22 21:03:12

2

在第二个例子中,你a,声明类型Tb变量无法转换为String,这是+所需的参数类型,推断从您的程序(即在没有任何其他信息的情况下应用于参数+的类型视图)。

在第一个例子中,推论可以猜出正确的+函数是否适用,考虑到它将参数列表中的元素类型作为参数,并且幸好在类型声明中提到了这些元素的类型是Int。尝试打字

"1"+2 

1 + 2 

...在REPL中,看看Scala试图做什么。然后阅读约views。现在

,我推测,通过使用上面类型参数T,您要编写与任何数值类型工作的功能,不是吗?在这种情况下,您可以使用Numeric特质。我会告诉你implicits读了前提示如下:

def matchList[T](ls: List[T])(implicit n:Numeric[T]): List[T] = { 
    import n.mkNumericOps 
    ls match { 
    case 1 :: rest => rest 
    case a :: b :: rest => (a + b) :: rest 
    case _ => ls 
}} 

你得到:

matchList(List(1,2,3)) 
res2: List[Int] = List(2, 3) 
matchList(List(2,3,4)) 
res4: List[Int] = List(5, 4) 
matchList(List(2.0,3.0,4.0)) 
res5: List[Double] = List(5.0, 4.0) 
相关问题