Currying的下限 - 可以简化?

时间:2017-03-07 14:11:14

标签: scala scalaz currying lower-bound

我想在利用scalazs disjunction的自己的错误类型中包装异常。

以下代码应该编译

trait Result
trait Error extends Result
object MyError extends Error
object OK extends Result

val r: Error \/ OK.type = tryCatchIn(_ => MyError /*:Error*/) {
  val result: Error \/ OK.type = ???
  result
}

我想保留咖喱语法,不喜欢明确键入MyError

我目前的解决方案是双重使用

  def tryCatchIn2[L, R](exceptionTransformer: Throwable => L, `finally`: => Unit = () => ()): CatchFinally[L] = {
    new CatchFinally(exceptionTransformer, `finally`)
  }

  class CatchFinally[L](val exceptionTransformer: Throwable => L, `finally`: => Unit = () => ()) {
    def apply[L2 >: L, R](block: => L2 \/ R): L2 \/ R = try {
      block
    } catch {
      case NonFatal(e) => -\/(exceptionTransformer(e))
    } finally {
      `finally`
    }
  }

我最初的咖喱方法会更好地反映我的意图,但我可以让它运转起来:

  def tryCatchIn[L, R, L2 >: L](exceptionContainer: Throwable => L, `finally`: => Unit = () => ())
                               (block: => L2 \/ R): L2 \/ R = {
    try {
      block
    } catch {
      case NonFatal(e) => -\/(exceptionContainer(e))
    } finally {
      `finally`
    }
  }

更清晰的解决方案是否可行?

1 个答案:

答案 0 :(得分:0)

也许我错过了你的一些意图,但这段代码不会更简单:

UPDATE ACCOUNTS SET STATUSID = 5 WHERE ACCOUNTNAME = '#ACCOUNTNAME' AND STATUSID = 4

E.g。只返回def tryCatchIn[L, R](exceptionContainer: Throwable => L, `finally`: => Unit = ()) (block: => R): L \/ R = { try { \/-(block) } catch { case NonFatal(e) => -\/(exceptionContainer(e)) } finally { `finally` } } ,最后只是R而不是(),不需要类型欺骗。如果你甚至愿意解雇finally块,你可以这样做:

() => ()

如果您希望解决方案正常工作,您将需要此功能签名:

def catchMe[L,R](exceptionContainer: Throwable => L)(block: =>  R) : L \/ R = {
   Try {block}.toDisjunction.leftMap(exceptionContainer)
}

因为def tryCatchIn[L, R, L2 >: L](exceptionContainer: Throwable => L2, `finally`: => Unit = () => ()) (block: => L \/ R): L2 \/ R 被定义为\/。使用\/[+A,+B]技巧是解决方案,但您还需要使用正确的返回类型。