scala:类型不匹配错误 - 找到T,必需字符串

时间:2011-12-22 20:43:03

标签: scala types

我正在学习scala,这个问题可能很愚蠢,但是......为什么?

例如,这没关系:

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

为什么?

4 个答案:

答案 0 :(得分:9)

对于任何类型T,操作T + T没有任何意义。 (所有类型都支持+吗?不会。想想添加两只狗或两名员工。)

在您的情况下,字符串连接运算符被调用(通过any2stringadd pimp添加),其返回类型(显然)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
}

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

在第一个例子中,推理可以猜测要应用的正确+函数,考虑它将列表元素的类型作为参数,谢天谢地,你在类型声明中提到了类型这些元素是+。尝试输入

Int

...在REPL中看看Scala尝试做什么。然后阅读views

现在,我推测通过使用上面的类型参数"1"+2 1 + 2 ,您正在尝试编写一个与任何数字类型一起使用的函数,不是吗?在这种情况下,您可以使用T特征。在建议以下内容之前,我会让您阅读implicits

Numeric

你得到:

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
}}

答案 3 :(得分:0)

没有任何导入:

passport.use(new SlackStrategy({
    clientID         : secret.slack.id,
    clientSecret     : secret.slack.secret,
    skipUserProfile  : false,
    callbackURL      : '/sessions/slack/callback',
    // scope            : ['channels:read', 'chat:write:bot', 'identity.basic'],
    scope            : ['identity.basic', 'identity.email', 'identity.avatar', 'identity.team', 'channels:read', 'chat:write:bot'],
    passReqToCallback: true
    }, (req, accessToken, scopes, profile, done) => {

    // Code to process the response
    })
)