2017-03-07 10 views
1

スカラッツの論理和を利用して、独自のエラータイプで例外をラップしたいと思います。カリング付き下限 - 簡略化可能?

次のコードは、

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のみを返し、最後に() =>()の代わりに()となり、トリッキーの必要はありません。あなたも、最終的にあなたが行うことができますブロック解任して喜んでいる場合:\/\/[+A,+B]のように定義されているため

def tryCatchIn[L, R, L2 >: L](exceptionContainer: Throwable => L2, `finally`: => Unit =() =>()) 
         (block: => L \/ R): L2 \/ R 

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

あなたはあなたのソリューションが動作するようにしたい場合は、あなたは、この機能の署名が必要になります。 L2 :> Lのトリックを使用することもできますが、正しい戻り値の型を使用する必要があります。

+0

型を正しく推論することはできません。上記の例のコードをコンパイルしてみてください。 –

+0

うーん、しました。たとえIntelliJワークシートでも、型を推測するのが悲惨に失敗しても、正常に動作します。 val result = tryCatchIn(e => s "例外が発生しました:$ {e.getMessage}"、println( "finally"))(1/0) val result2 = catchMe s "例外が発生しました:$ {e.getMessage}")(1/0) '' ' どちらもString \/Intとして推測されます。 – Markus

+0

'trait Result'、' object MyError'などの3行目からサンプルコードを試しましたか? –

関連する問題