(Play2.0を使用して)リモートサービスにアクセスするための完全に非同期のライブラリを作成しているので、失敗と有効な結果を同時に提示するタイプのノンブロッキング呼び出しを使用Promise
して作成しています。Validation
Promise
Play2-scalaから来ており、Validation
scalazから来ています。
だからここにそのような関数の例のタイプがあります
- f ::
A => Promise[Validation[E, B]]
- g ::
B => Promise[Validation[E, C]]
これまでのところ、とても良いですが、今、それらを作成したい場合は、をPromise
提示するという事実を簡単に使用flatMap
できるので、理解のためにそれを行うことができます
for (
x <- f(a);
y <- g(b)
) yield y
Validation
わかりました。理解のために結果を再利用しなかったので、ここで問題への近道を取りました。x
で再利用したい場合g
は、次のようにできます
for (
x <- f(a); // x is a Validation
y <- x.fold(
fail => Promise.pure(x),
ok => g(ok)
)
) yield y
十分に公平ですが、この種の定型文は私のコードを何度も汚染することになります。ここでの問題は、のような2レベルのモナディック構造を持っていることですM[N[_]]
。
この段階で、セコンレベルを簡単にスキップすることでそのような構造を操作できるようにするf°プログラミングの構造はありますか?
for (
x <- f(a); //x is a B
y <- g(b)
) yield y
さて、以下は私が似たようなことを達成した方法です。
2つのレベルを1つにラップする一種のモナディック構造を作成しました。たとえば、2つのメソッドでタイプValidationPromised
を刺激したとします。Promise
def /~> [EE >: E, B](f: Validation[E, A] => ValidationPromised[EE, B]): ValidationPromised[EE, B] =
promised flatMap { valid =>
f(valid).promised
}
def /~~>[EE >: E, B](f: A => ValidationPromised[EE, B]): ValidationPromised[EE, B] =
promised flatMap { valid =>
valid.fold (
bad => Promise.pure(KO(bad)),
good => f(good).promised
)
}
これは私がそのようなことをすることを可能にします
endPoint.service /~~> //get the service
(svc => //the service
svc.start /~~> (st => //get the starting elt
svc.create(None) /~~> //svc creates a new elt
(newE => //the created one
newEntry.link(st, newE) /~~> //link start and the new
(lnk => Promise.pure(OK((st, lnk, newE)))) //returns a triple => hackish
)
)
)
ご覧/~~>
のとおり、非常に似てflatMap
いますが、1つのレベルをスキップします。問題は冗長性です(そのため、Scalaには「for-comprehension」が存在し、Haskellには「do」が存在します)。
もう1つのポイントは、これも/~>
同じようにmap
機能しますが、(有効なタイプではなく、第3レベルの)第2レベルで機能することです。
それで、私の2番目の質問は前者の当然の結果です...私はこの構造で持続可能な解決策を承認していますか?
長くてごめんなさい