2015-01-31 3 views
6

У меня проблема с типами, которые я не понимаю. В приведенном ниже коде у меня есть два метода: half1 и half2, которые являются точно такими же, за исключением того, что тип возврата half1 указан явно. Тем не менее, когда я использую два метода в foldLeft half, возникает ошибка компилятора. Вот код. Проблема связана с строкой, которая устанавливает val c.Ошибка типа Scala с помощью Try [Int]

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 comile в foldLeft, но half2 не делает? Я использую Scala 2.11.5

ответ

8

Оба Success и Failure продлить Try[T] with Product with Serializable, (Product 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], и таким образом вы получаете несоответствие типа. Использование вывода типа может быть приятным, но большую часть времени явным образом набираю возвращаемые типы, вы сэкономите много головных болей.

Смежные вопросы