その特定の実装に対して最も理にかなっています。生成アダプタ
object FooImpl1 extends FooInterface[Option] { ... }
object FooImpl2 extends FooInterface[Future] { ... }
object FooImpl3 extends FooInterface[({type X[Y] = ReaderT[Future, Database, Y]})#X] { ... }
すべての実装は完全に有効です。すべての結果は、特定の高級タイプでラップされた結果を返します。
私はその後、多くの場合のは、私はコンテキストとしてFuture
を使用していると働いているロジックのブロックでは、私はこのような何か書くかもしれないと言わせて、いくつかのビジネスロジックを書くことに来る:
val foo: FooInterface[Future] = ???
def fn(): Future[Int] = Future { 42 }
val result: Future[Int] = for {
x <- foo.barA()
y <- foo.barB()
z <- foo.barC()
w <- fn()
} yield x + y + z + w
上記のコードをFooImpl2
で本当にうまくいくでしょうが、他の実装は直接スロットに入れません。このシナリオでは、私はいつも簡単なアダプタを書く羽目になる:特に機能の多くが付いているインタフェースに対して、アダプタを書く
object FooImpl1Adapter extends FooInterface[Future] {
val t = new Exception ("Foo impl 1 failed.")
def barA(): Future[Int] = FooImpl1.barA() match {
case Some (num) => Future.successful (num)
case None => Future.failed (t)
}
def barB(): Future[Int] = FooImpl1.barB() match {
case Some (num) => Future.successful (num)
case None => Future.failed (t)
}
def barC(): Future[Int] = FooImpl1.barC() match {
case Some (num) => Future.successful (num)
case None => Future.failed (t)
}
}
case class FooImpl3Adapter (db: Database) extends FooInterface[Future] {
def barA(): Future[Int] = FooImpl3.barA().run (db)
def barB(): Future[Int] = FooImpl3.barB().run (db)
def barC(): Future[Int] = FooImpl3.barC().run (db)
}
は結構ですが、それは定型の多くが含まれます。さらに、それぞれのメソッドがそれぞれのメソッドに対してまったく同じ適応処理を取得するということです。私が本当にしたいのは、lift
アダプターの実装を既存の実装から、アダプテーションメカニズムで1回だけ指定することです。
私はこのような何かを書くことができるようにしたいと思います:
def generateAdapterFn[X[_], Y[_]] (implx: FooInterface[X])(f: X[?] => Y[?]): FooInterface[Y] = ???
は、だから私はそうのようにそれを使用することができます。
val fooImpl1Adapter: FooInterface[Future] = generateAdapterFn [?, Future]() { z => z match {
case Some (obj) => Future.successful (obj)
case None => Future.failed (t)
}}
質問は:どのように私はgenerateAdapterFn
機能を書くことができます?
私は実際にこれを解決する方法や、他によくあるパターンや解決策があるかどうかはわかりません。私はgenerateAdapterFn
機能を書いていると思います。私はマクロを書く必要がありますか?もしそうなら、どうすればいいのでしょうか?
本当に助かりました。何が起きているかを正式に指定します。特定のインタフェースの実装が多種多様であるシナリオでは、generateAdapter fnは多くの定型文の作成を節約します。 – sungiant
ここには2つの質問がありますが、そのうちの最初の方がうまく答えていますが、これから続けるためにはgenerateAdaptor関数を定義するときに書かれたコードは事実上規範的ですが、これは特に多くの関数この例のものよりもこれを直接書くのではなく、代わりに実装を生成する方法はありますか?多分リフレクション... – sungiant