1

我目前正在尝试解决一些 Scala 问题集以了解该语言。我遇到了问题 11,我的解决方案无法编译。我的问题是:为什么这在 Scala 中是非法的?

def countPackSingle[A](list: List[A]): List[Any] = {
  pack(list) map {ls => {
    case head :: Nil => head
    case head :: tail => List(tail.size + 1, head)
  }}
}

IntelliJ 对此定义很满意,但编译器抱怨:

扩展函数缺少参数类型
匿名函数的参数类型必须是完全已知的。(SLS 8.5)

预期类型是:?

pack(list) map {ls => {
                      ^

我真的不明白这条消息试图告诉我什么。scala 编译器不能推断出的类型ls吗?当我通过 指定类型时ls: List[A],问题仍然存在。

ls在这种情况下:为什么我可以在使用花括号时指定参数的类型,而{ }在使用括号时却不能( )?直到今天,我一直在寻找一个很好的资源来解释 Scala 的不同之处。到目前为止,我相信只有在使用字面量通过 `case和其他一些极少数情况下创建偏函数时才会产生真正的不同。

感谢帮助!

4

1 回答 1

4

这种结构:

{
  case head :: Nil => head
  case head :: tail => List(tail.size + 1, head)
}

是部分函数的语法糖,这就是编译器向您抛出此消息的原因,scalac 认为您正在尝试制作PartilFunction[List[A], List[A]]. 要解决此问题,您有三种方法:

1)完成此模式匹配构造:

pack(list) map { ls => ls match {
    case head :: Nil => head
    case head :: tail => List(tail.size + 1, head)
  }
}

2) 使用下划线语法:

pack(list) map { _ match {
    case head :: Nil => head
    case head :: tail => List(tail.size + 1, head)
  }
}

这实际上是一样的。现在,如果你愿意,你可以为 ls 赋予一个类型,但 scala 可以成功地推断出它。

3)使用内联语法:

pack(list) map {
  case head :: Nil => head
  case head :: tail => List(tail.size + 1, head)
}

可能因为PartialFunction是 的子类Function,所以可以直接使用偏函数而不是普通函数。

而且你对结果类型没有任何意义List[Any]。1)这种类型不好,导致你丢失了所有类型信息 2)你的函数不是尾递归的,所以你可以放弃它,让 scalac 为你推断它

于 2013-09-27T12:51:52.823 回答