使用函数文字输入推理

时间:2013-09-27 12:45:20

标签: scala function-literal

我正在尝试解决some Scala problem set以了解该语言。我遇到问题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的不同之处。到目前为止,我认为它只会产生real difference when using the literals to create parial functions via `case以及其他一些罕见的情况。

感谢您的帮助!

1 个答案:

答案 0 :(得分: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)
}

有可能因为PartialFunctionFunction的子类,所以可以直接使用部分函数而不是普通函数。

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