6

我对我不理解的类型有疑问。在下面的代码中,我有两个方法half1half2它们完全相同,除了half1显式指定的返回类型。然而,当我在 foldLeft 中使用这两种方法时half会导致编译器错误。这是代码。设置的线路val c有问题。

package org.bodhi.reactive.`try`

import scala.util.{Try, Success, Failure}

object Hello {
   def main(args: Array[String]): Unit = {

    val list = List(1,2,3)

    Try(1024).flatMap(half1)
    Try(1024).flatMap(half2)

    half1(1024).flatMap(half1)
    half2(1024).flatMap(half2)

    val a = list.foldLeft(Try(1024))((accum, n) => accum.flatMap(half1))
    val b = list.foldLeft(half1(1024))((accum, n) => accum.flatMap(half1))
    val c = list.foldLeft(half2(1024))((accum, n) => accum.flatMap(half2)) // Compiler error

  }

  def half1(n: Int): Try[Int] =  
    if (n % 2 == 0) Success(n / 2)
    else Failure(new Exception(s"WRONG $n"))

  def half2(n: Int) =
    if (n % 2 == 0) Success(n / 2)
    else Failure(new Exception(s"WRONG $n"))
}

我得到的错误是:

[error] /home/chris/projects/reactive/example/src/main/scala/org/bodhi/reactive/try/Hello.scala:18: type mismatch;
[error]  found   : scala.util.Try[Int]
[error]  required: Product with Serializable with scala.util.Try[Int]
[error]     val c = list.foldLeft(half2(1024))((accum, n) => accum.flatMap(half2))

我的问题是:为什么会half1在 foldLeft 中出现,但half2没有?我正在使用 Scala 2.11.5

4

1 回答 1

8

Success和extend FailureTry[T] with Product with SerializableProduct with Serializable因为它们是案例类)。所以当你离开返回类型时half2,它的返回类型被推断为Try[T] with Product with Serializable

通常这无关紧要,flatMap(half2)仍然会返回Try[T]

scala> Try(1024).flatMap(half2)
res2: scala.util.Try[Int] = Success(512)

但又foldLeft是另一回事了。问题是当您half(2)作为第一个参数传递时。让我们看一下 的签名foldLeft

def foldLeft[B](z: B)(op: (A, B) => B): B

B是从参数中推断出来的z,这意味着

B = Try[T] with Product with Serializable

这意味着op预计将具有以下类型:

(A, Try[T] with Product with Serializable) => Try[T] with Product with Serializable

但相反,它是(A, Try[T]) => Try[T],因此您会得到类型不匹配。使用类型推断可能会很好,但大多数时候显式输入返回类型将为您省去很多麻烦。

于 2015-01-31T17:10:20.463 回答