尝试制作将函数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
没有被调用?
答案 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"}) }