18

私は遊びを持っています!2外部サービスからJSON形式のデータを取得する必要があるScalaアプリケーションの場合。

遊び!フレームワークでは、応答をPromiseでラップすることにより、HTTPリクエストを非同期で作成できます。Promiseは、将来利用可能になる値をラップするモナドです。

これは問題ありませんが、私の場合、Webサービスから取得するのはJSON文字列です。解析する必要があり、解析が失敗する可能性があります。だから私は私が入るものは何でもラップする必要がありOptionます。その結果、私のメソッドの多くがを返していPromise[Option[Whatever]]ます。つまり、Whatever後で利用可能になる可能性のあるタイプの値です。

今、私がそのような値を操作しなければならないときはいつでも、私はmapそれを2回行う必要があります。私はこれを次のように扱うことを考えていました:

  • Hope[A]たとえば、をラップする新しいタイプを作成しますPromise[Option[A]]
  • 次のような関連するメソッドを定義しますmap(またはforeach、コレクションの特性を使用して継承する必要がありますか?)flatten
  • Promise[Option[A]]との間の暗黙的なコンバータを提供しHope[A]ます。

定義するのは簡単ですmap-2つのファンクターの合成もファンクターです-flattenこの場合、またはでモナドを構成するときはいつでも明示的に行うことができますOption

しかし、私がこのようなものを再発明する必要がないことは私の限られた理解です。モナド変換子はまさにこの場合に存在します。または、まあ、私は思う-私はモナド変換器を使用したことがない-そしてこれが質問のポイントです:

この状況でモナドトランスフォーマーを使用できますか?実際にどのように使用しますか?

4

2 に答える 2

14

Scalazライブラリのトランスフォーマーを使用すると、タイプの値OptionTをタイプの値に変換できるはずです。Promise[Option[A]]OptionT[Promise, A]

Scalaz 7の使用:

import scalaz.OptionT._
val x: OptionT[Promise, Int] = optionT(Promise.pure(Some(123)))

この値を使用するには、たとえば、呼び出しmapや呼び出しを行うために、 (for 、for )flatMapに適切な型クラスを指定する必要があります。PromiseFunctormapMonadflatMap

はモナディックなのでPromise、のインスタンスを提供できるはずですMonad[Promise]。(型クラスは継承階層を形成するため、無料で入手できます。)例(注:これはテストしていません!Functor):Applicative

implicit val promiseMonad = new Monad[Promise] {
  def point[A](a: => A): Promise[A] = Promise.pure(a)
  def bind[A, B](fa: Promise[A])(f: A => Promise[B]): Promise[B] = fa flatMap f
}

簡単な例として、でを使用mapしてOptionT[Promise, A]、タイプの関数をA => B内部の値に適用できます。

def foo[A, B](x: OptionT[Promise, A], f: A => B): OptionT[Promise, B] = x map f

Promise[Option[A]]から基になる値を取得するOptionT[Promise, A]には、メソッドを呼び出しますrun

def bar[A, B](x: Promise[Option[A]], f: A => B): Promise[Option[B]] =
  optionT(x).map(f).run

OptionT[Promise, _]互換性のあるタイプの複数の操作を構成し、操作間でタイプを保持し、最後に基になる値を取得できる場合は、モナド変換子を使用することでより多くのメリットが得られます。

理解のために操作を構成するには、タイプの関数が必要になりますA => OptionT[Promise, B]

于 2012-09-03T13:13:39.943 に答える
1

-削除-

編集:

さて、あなたはここで単に使うことができscalaz.OptionTます:

val x = optionT(Promise { /* api call */ some("""{ "foo": "bar" }""") })
val mapped = x.map(Json.parse).run // run return the resulting Promise[Option[T]]
于 2012-09-03T12:23:00.807 に答える