Question

Trying to make implicit method that converts function a: => T to 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"
}

Why my implicit def is not being called?

Was it helpful?

Solution

Here is the same scenario with 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"}) }

refer https://issues.scala-lang.org/browse/SI-3237 for more details on this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top