使用Validation.fromTryCatch使用by-name参数进行隐式转换

时间:2013-12-03 11:34:45

标签: scala scalaz

尝试制作将函数a: => T转换为Validation[Throwable, String]

的隐式方法
//works correctly
val t3 = test3
t3.fold(e => println("got error: " + e), s => println("got success: " + s.toString))

def test3: Validation[Throwable, String] ={
    Validation.fromTryCatch{
      throw new RuntimeException()
      "success"
    }
}

//does not work, exception is being thrown
val t4 = test4
implicit def trycatch2v[T](a: => T): Validation[Throwable, T]  = Validation.fromTryCatch(a)

def test4: Validation[Throwable, String] ={
      throw new RuntimeException()
      "success"
}

为什么我的implicit def没有被调用?

1 个答案:

答案 0 :(得分:2)

以下是与Try相同的情况。

def test3: Try [String] = Try { throw new RuntimeException(); "success" }

test3 // works fine.


implicit def toTry[T](a: => T): Try[T] = { println("convert to try!"); Try(a) }

def test4: Try[String] = { throw new RuntimeException(); "success"}


{ throw new RuntimeException(); "success"  }.getOrElse("failed") // works fine.

// type checker finds that the return type of block is String,
//   which does not have a getOrElse 
// so it falls back on implicit conversion for the block. as follows:

toTry( {throw new RuntimeException(); "success"  }).getOrElse("failed") 


test4 // gives runtime exception

 // test4 has an *expected type* of Try[String]
 // The return type of block is String ("success")
 // So implicit conversion kicks in from ':=> String' to 'Try[String]' 
 // this conversion is not for the outer block but for the inner block.

 // so in essence, it is converted to:

 def test4: Try[String] = { throw new RuntimeException(); toTry({"success"}) }

请参阅https://issues.scala-lang.org/browse/SI-3237了解详情。