我正在学习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
为什么?
答案 0 :(得分:9)
对于任何类型T
,操作T + T
没有任何意义。 (所有类型都支持+
吗?不会。想想添加两只狗或两名员工。)
在您的情况下,字符串连接运算符被调用(通过any2stringadd
pimp添加),其返回类型(显然)String
。因此错误信息。
您需要一种方式来指定类型T
必须支持您组合两个T
类型值的操作,以产生新值键入T
。 Scalaz的Semigroup
完全符合该法案。
以下作品:
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)
,+
运算符的唯一普遍用法是字符串连接,因此a
和b
必须都是字符串(或自动可转换为字符串)以使其有效。您的参数化类型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
})
)