7

(Play2.0を使用して)リモートサービスにアクセスするための完全に非同期のライブラリを作成しているので、失敗と有効な結果を同時に提示するタイプのノンブロッキング呼び出しを使用Promiseして作成しています。Validation

PromisePlay2-scalaから来ており、Validationscalazから来ています。

だからここにそのような関数の例のタイプがあります

  • 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番目の質問は前者の当然の結果です...私はこの構造で持続可能な解決策を承認していますか?

長くてごめんなさい

4

1 に答える 1

4

ここで探しているコンセプトはモナド変換子です。簡単に言うと、モナド変換子は、モナドを「スタック」できるようにすることで、構成されていないモナドを補正します。

使用しているScalazのバージョンについては言及していませんが、scalaz-sevenブランチを見ると、 ValidationTが見つかります。F[Validation[E, A]]これは、任意のものをにラップするために使用できます。このValidationT[F, E, A]場合、F = Promise。変更fgて戻るValidationT場合は、コードを次のように残すことができます

for {
  x ← f(a)
  y ← g(b)
} yield y

これValidationT[Promise, E, B]により、結果としてが得られます。

于 2012-06-10T16:09:21.343 に答える