2

Action を Future にマップするために scalaz.Free を使用する例を 1 つ書きました。しかし、私はその利点を理解しようとしています。ここで答えが得られることを願っています。ここに私のコードスニペットがあります

まず、AST であるアクションを作成します。

trait Action[A]

case class GetNumberAction(x: Int) extends Action[Int]
case class GetStringAction(x: String) extends Action[String]
case class ConvertToIntAction(x: String) extends Action[Int]
case class AddAction(x: Int, y: Int) extends Action[Int]

次に、Scalaz Free と Coyonda を使用して Action を ASTMonad にマップするクラスを作成します。

type Functor[A] = Coyoneda[Action, A]
type ASTMonad[A]= Free[Functor, A]

def toMonad[A](action: Action[A]): ASTMonad[A] = Free.liftFC[Action, A](action) 

object ADTMonad {
    def getNumber(x: Int): ASTMonad[Int] = toMonad(GetNumberAction(x))
    def getString(x: String): ASTMonad[String] = toMonad(GetStringAction(x))
    def converToInt(x: String): ASTMonad[Int] = toMonad(ConvertToIntAction(x))
    def add(x: Int, y: Int): ASTMonad[Int] = toMonad(AddAction(x, y))

}

最後に、Action を Future に解釈する Interpreter を作成します。

object Interpreter extends (Action ~> Future) {
    def apply[A](action: Action[A]): Future[A] = {
        action match {
            case GetNumberAction(x) => Future(x)
            case GetStringAction(x) => Future(x)
            case ConvertToIntAction(x) => Future(x.toInt)
            case AddAction(x, y) => Future(x + y)
        }
    }
}

実行すると、使用できます

val chain =  for {
    number <- ASTMonad.getNumber(x)
    str <- ASTMonad.getString(y)
    convertedNumber <- ASTMonad.converToInt(str)
    total <- ASTMonad.add(number, convertedNumber)
    } yield total

chain.runWith(Interpreter)

それは機能しているようで、このモナドとインタープリターのことを理解していると思います。ただし、 Future.flatmapmapを直接使用している場合、ソリューションと比較してどのような利点があると考えていますか?

for {
    number <- Future(x)
    str <- Future(y)
    convertedNumber <- Future(str.toInt)
    total <- Future(number + convertedNumber)
} yield total

Future flatmap と map を使用するコードは、私には単純に見えます。私の質問に戻りますが、Future はすでに flatMap と map を提供しているので、Free モナドを使用してビジネス ロジックを Future に解釈する必要がありますか。もしそうなら、誰かが私にもっと具体的な例を教えてくれるので、その利点を見ることができますか?

前もって感謝します

4

1 に答える 1

0

free applicative を使用する良い例は、コマンド ライン パーサーです。 type と呼びましょうCLI[A]

type の値は、コマンドライン引数 ( ) を指定し、それらを正常に解析できる場合CLI[A]に取得されることを意味します。現在、この機能は、エラー処理に使用する場合と同形です。AArray[String]Array[String] -> Either[String,A]Either

CLIapplicative にしたので、値をmapand apply(結合) することができます。たとえば、Int引数count、別のInt引数を作成し、それらを組み合わせて合計を保持count2する最終的なものにすることができます。sum: CLI[Int]

計算を直接適用すると仮定すると、これは に「のみ」相当するものを生成しArray[String] -> Either[String,Int]ます。しかし、ヘルプ テキストを作成したい場合は、両方の最初の引数を知っている必要があり、この情報は失われます。

Free救助へ。を使用すると、引数から直接解析されるFreeすべての初期値を抽出するために使用できる計算グラフを保持できます。その後、すべての初期引数の解析結果を提供することによりCLI、 の最終値を生成する計算を後で実行できます。sum

もちろんCLI、計算ですべての初期値を追跡する特別なものを実装することもできますがFree、この余分な作業は避けましょう。

于 2015-12-13T20:56:31.427 に答える