4

在学习了很多 Java 和一些 Haskell 之后,我想看看 Scala。从下面的代码中,我收到此错误消息

type mismatch; found : List[Nothing] => Option[Nothing] required: List[Int] => Option[Nothing]

我不知道我做错了什么:

object MyFirstScalaObject {

  def main(args: Array[String]) {
      lazy val testValues:List[List[Int]] = List((1 to 10).toList, null, List());

      println(  testFunction(last, testValues));
  }

  def testFunction[I, O](f : I => O, inputs : List[I]):
      List[(I, O)] = 
    inputs.zip(inputs.map(f));

  def last[A](xs:List[A]):Option[A] = xs match {
    case x::Nil => Some(x);
    case _::xs => last(xs);
    case _ => None;
  }

}

感谢您的任何建议。

干杯,

4

3 回答 3

3

由于 scala 中类型推断的工作方式,它无法确定类型参数必须last是什么,因此它必须采用过于保守的后备猜测它是Nothing.

您可以在调用时显式指定类型testFunction

testFunction[List[Int],Option[Int](last, testValues)

或者您可以更完整地记录声明中类型参数之间的关系testFunction,这将为类型推断器提供更多信息:

def testFunction[A, I[_], O[_]](f : I[A] => O[A], inputs : List[I[A]]): List[(I[A], O[A])]

这明确表示 I 和 O 是类型构造函数(kind * -> *),现在 f 的输入/输出类型更加具体,推理器可以正确推断最后一个函数的 A 参数必须是 Int。

于 2012-12-14T20:05:56.327 回答
1

一个完全修改和测试的版本,使用了 senia 的想法:

object MyFirstScalaObject {
  def main(args: Array[String]) {
      lazy val testValues = List((1 to 10).toList, null, List())
      println(testFunction(testValues)(last))
  }

  def testFunction[I, O](inputs: List[I])(f: I => O): List[(I, O)] =
    inputs.zip(inputs.map(f))

  def last[A](xs: List[A]): Option[A] = xs match {
    case x :: Nil => Some(x)
    case _ :: xs => last(xs)
    case _ => None
  }
}

类型推断从左到右进行;来自一个参数列表的信息用于下一个参数列表。在这段代码中,当你调用testFunctionScala 时,可以I从第一个参数中推导出来,然后它可以I作为函数的输入类型f来判断它的类型(即参数last是用 应用的A = Int),然后它最终得到的值O从函数的返回类型。

于 2012-12-15T00:18:52.607 回答
1

我不能告诉你为什么 scala 中的类型推断是这样工作的。

但是在这种情况下,有一种常见的方法可以帮助编译器 - parameter sections.

def testFunction[I, O](inputs : List[I])(f: I => O): List[(I, O)] = inputs.zip(inputs.map(f))

用法:

testFunction(testValues)(last)

类似的解决方案是将方法添加testFunction到类List

class LastsHelper[T](inputs: List[T]) {
  def testFunction[O](f: T => O): List[(T, O)] = inputs.zip(inputs.map(f))
}
implicit def toLastsHelper[T](inputs: List[T]) = new LastsHelper(inputs)

您可以使用以下方法,例如List

testValues.testFunction(last)
于 2012-12-15T05:25:26.883 回答