如何跳过包装尝试参数已经是Try-instance?

Ale*_*dar 0 scala

假设我有一个包装块的方法Try:

def wrapToTry[T](arg: =>T):Try[T] = Try(arg)

那么如果arg传递的话已经是一个实例Try[U]?我希望在这种情况下包装方法只返回arg自己而不包装.到目前为止,我想出的唯一方法是:

def wrapToTry[T,U](arg: =>T):Try[U] = if(arg.isInstanceOf[Try[U]]) arg.asInstanceOf[Try[U]] else Try(arg).asInstanceOf[Try[U]]

我真的不喜欢它,并试图弄清楚如何解决它.首先我试着超载:

def wrapToTry[T](arg: =>T):Try[T] = Try(arg)

def wrapToTry[T](arg: =>Try[T]):Try[T] = arg
Run Code Online (Sandbox Code Playgroud)

但由于编译错误导致类型擦除,因此无法编译

Error:(10, 7) double definition:
def wrapToTry[T](arg: => T): scala.util.Try[T] at line 8 and
def wrapToTry[T](arg: => scala.util.Try[T]): scala.util.Try[T] at line 10
have same type after erasure: (arg: Function0)scala.util.Try
  def wrapToTry[T](arg: =>Try[T]):Try[T] = arg
      ^
Run Code Online (Sandbox Code Playgroud)

好的,我明白了,这是因为参数是按名称,经验教训.然后我的想法是使用以下代码段中的证据创建方法的重载版本:

object Test {
  import scala.util.Try
  import scala.util.Success

  def wrapToTry[T](arg: =>T):Try[T] = Try(arg)

  def wrapToTry[T, U](arg: =>T)(implicit evidence: T <:< Try[U]) = arg

  def main(args:Array[String]):Unit = {
    println(wrapToTry("alex"))
    println(wrapToTry(Success("alex")))
  }

}
Run Code Online (Sandbox Code Playgroud)

但由于以下编译器错误的模糊性,这不会编译:

Error:(15, 13) ambiguous reference to overloaded definition,
both method wrapToTry in object Test of type [T, U](arg: => T)(implicit evidence: <:<[T,scala.util.Try[U]])T
and  method wrapToTry in object Test of type [T](arg: => T)scala.util.Try[T]
match argument types (String) and expected result type Any
    println(wrapToTry("alex"))
            ^
Run Code Online (Sandbox Code Playgroud)

我相信应该有一种优雅的方式来实现这一点.你能建议吗?

***************************************UPDATE*************************************

根据读者的要求,认为这个问题中的问题在这里是无用的,这就是出现问题的背景.

TLDR

我有一个DSL来简化ScalaTest套件的工作.此DSL实施的一部分是:

class Test(block: => Assertion){

    def afterThat[T, U](followUp: =>T):Assertion = {
      val start = Try(block)
      val followUpAttempt:Try[U] = if(followUp.isInstanceOf[Try[U]]) followUp.asInstanceOf[Try[U]] else Try(followUp.asInstanceOf[U])
      start.flatMap(r => followUpAttempt.map(_ => r)).get
    }

  }

  object Test{
    def apply(body: => Assertion):Test = new Test(body)
    implicit def assertionToTest(a: => Assertion):Test = new Test(a)
  }
Run Code Online (Sandbox Code Playgroud)

这允许我编写如下测试:

"Admin" should "be able to create a new interest segment" in{
    val group = interestsGroup
    val segment = tempInterestSegment
    Test{
      Given("an existing interests segment group")
      SegmentGroupsPage.open
      SegmentGroupsPage.createNewSegmentGroup(group)
      And("admin is on Segments view")
      SegmentsPage.open
      When("he creates a new interest segment in this segment group")
      SegmentsPage.createNewSegment(segment)
      Then("this segment is shown in the list")
      SegmentsPage.isParticularSegmentShownInTheList(segment.name) shouldBe true
      And("it has correct values on its details view.")
      SegmentsPage.openSegmentDetailsView(segment.name)
      SegmentsPage.fieldsHaveCorrectValues(segment) shouldBe true
    } afterThat cleanUpTest(segment, group)
  }
Run Code Online (Sandbox Code Playgroud)

我也可以afterThat在每次测试结束时尽可能多地使用.他们每个人都被包裹进去,Try所以我确信他们都被执行了,最后我仍然得到了我原来Assertion的结果.

然后我遇到了一个测试,我传递给后续块afterThat已经是一个Try实例.它会工作,但我简直不喜欢嵌套尝试所以决定运动,如果我能够解决这个问题.

fla*_*ian 5

我会在这里找到专门的暗示:

object Helpers {
  implicit class TryConverter[T](obj: => T) {
    def asTry: Try[T] = Try(obj)
  }

  implicit class TryIdentity[T](obj: => Try[T]) {
    def asTry: Try[T] = obj
  }
}
Run Code Online (Sandbox Code Playgroud)

现在编译器可以为你做类型魔术.

import Helpers._
Run Code Online (Sandbox Code Playgroud)

然后.asTry在您需要的任何地方打电话.你不应该用回归的东西进行中间化Any,为什么会自动失去类型专业化?