2015-01-31 25 views
6

Mam problem z typami, których nie rozumiem. W poniższym kodzie mam dwie metody: half1 i half2, które są dokładnie takie same, z wyjątkiem tego, że typ zwracany half1 jest określony jawnie. Jednak gdy używam tych dwóch metod w foldLeft half, powoduje to błąd kompilatora. Oto kod. Linia, która ustawia val c ma problem.Błąd typu Scala z próbą [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")) 
} 

Błąd pojawia się:

[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)) 

Moje pytanie brzmi: dlaczego half1 comile w foldLeft, ale half2 nie? Używam Scala 2.11.5

Odpowiedz

8

Zarówno Success i Failure przedłużyć Try[T] with Product with Serializable, (Product with Serializable bo są zajęcia przypadku). Tak więc, po odejściu od typu zwrotu od half2, zwracany typ jest określany jako Try[T] with Product with Serializable.

Normalnie to nie ma znaczenia, flatMap(half2) będzie jeszcze powrócić Try[T]

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

Ale foldLeft to zupełnie inna historia. Problem polega na tym, że jako pierwszy argument podaje się half(2). Spójrzmy na podpisaniu foldLeft:

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

B jest wywnioskować z argumentu z, co oznacza

B = Try[T] with Product with Serializable 

Oznacza to, że oczekuje op jest mieć typ:

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

Ale zamiast tego jest to (A, Try[T]) => Try[T], a zatem pojawia się niedopasowanie typu. Korzystanie z wnioskowania o typie może być miłe, ale w większości przypadków wyraźne wpisywanie typów zwrotu pozwoli zaoszczędzić wiele bólu głowy.

Powiązane problemy