2017-03-07 85 views
1

我想用自己的錯誤類型來包裝異常,並利用scalazs析取。柯里化的下界 - 可簡化?

下面的代碼應編譯

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` 
    } 
    } 

是一個清晰的解決方案可能?

回答

0

也許我錯過了一些你的意圖,但不會這個代碼簡單得多:

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]。使用L2 :> L技巧是解決方案,但您還需要使用正確的返回類型。

+0

它不能正確推斷類型 - 嘗試編譯上面的示例代碼 –

+0

嗯,我做到了。即使在IntelliJ工作表中,通常無法推斷類型的工作正常。 ''' val result = tryCatchIn(e => s「發生異常:$ {e.getMessage}」,println(「finally」))(1/0) val result2 = catchMe(e => s「發生異常:$ {e.getMessage}」)(1/0) ''' 這兩者都被推斷爲String \/Int。 – Markus

+0

你有沒有嘗試我的示例代碼開始在第三行與'特技結果','對象MyError'等? –