複数のモナドを同時に扱うためのネストfor式

## 前置き

さて、前置きですが、モナドと書きましたが実際にはモナドではなく、モナドのようなものです。
ここで言うモナドというものは、Scalaにおける`for`式で扱えるように、以下のメソッドを実装している型のことを指します。

* map/flatMap

（つまり、`for`式で使える型、ifフィルターとyieldではないfor式を除く）
あと、記事中の英語は適当です。

## はじめに

どこかで見た便利な書き方として`for`式のネストした形式を紹介します。（具体的な呼び名は知らない。勝手にネスト`for`式とか言っておく。）
Scalaでのエラーハンドリングはキモくなりがちです。
`Either`、`Try`、`Option`の入り混ざったものを一つの`for`式で扱うのは困難で、

最初に`for`式中で使用したモナドに、以降も制限されてしまいます。

```scala
scala> {
     |     for {
     |         result <- Future { Try("hanage") }
     |         hanage <- result
     |     } yield hanage
     | }
<console>:22: error: type mismatch;
 found   : scala.util.Try[String]
 required: scala.concurrent.Future[?]
               hanage <- result
                      ^
```

さて、この全部の失敗した結果をまとめてハンドリングしたいが、Scala標準ライブラリだけでやりたいです。
（関数型ライブラリなどをプロダクト開発に使おうとすると、扱える人が極端に限定されるので、個人的にはなるべく扱いたくない。）

## ネストfor式を使おう

標準の`for`式の構文は以下のようになっており、`seq`はジェネレーター、定義、フィルターを連続した形で指定する。連続した要素はセミコロンで区切られます。

```scala
for ( seq ) yield expr
```

この`expr`の部分に`for`式をネストした形で記述するのが`for`式のネストですね。（そのまま）

```scala
for ( seq ) yield {
    for ( seq ) yield {
        ...
    }
}
```

この各`for`式は、当然のように異なる`for`式なので、`for`式一つにつきモナドを使用することができますね。
つまり、複数のモナドを一つ（に見せかけた）の`for`式で扱いたい場合に使用することができます。

以下に実際に`Future`と`Try`をまとめてハンドリングしたネストfor式の例を、、

```scala
scala> {
     |     for {
     |         result <- Future { throw new Exception; Failure(new Exception) }
     |     } yield for {
     |         string <- result
     |     } yield string
     | } onComplete {
     |     case Success(Failure(_)) => println("Future is Success, but hanage is Failure")
     |     case Success(_) => println("Success All")
     |     case Failure(e) => println(s"Future is Failure, because of $e")
     | }
Future is Failure, because of java.lang.Exception
```

```scala
scala> {
     |     for {
     |         result <- Future { Failure(new Exception) }
     |     } yield for {
     |         string <- result
     |     } yield string
     | } onComplete {
     |     case Success(Failure(_)) => println("Future is Success, but hanage is Failure")
     |     case Success(_) => println("Success All")
     |     case Failure(e) => println(s"Future is Failure, because of $e")
     | }

scala> Future is Success, but hanage is Failure
```

```scala
scala> {
     |     for {
     |         result <- Future { Success(new Exception) }
     |     } yield for {
     |         string <- result
     |     } yield string
     | } onComplete {
     |     case Success(Failure(_)) => println("Future is Success, but hanage is Failure")
     |     case Success(_) => println("Success All")
     |     case Failure(e) => println(s"Future is Failure, because of $e")
     | }
Success All
```

Futureによって、ネストされたfor式は別スレッドで実行されます。
全ての処理が完了した時の処理をonCompleteに記述します。

onCompleteに渡すのはPartialFunctionなので、エラーハンドリングは別の関数として定義しておいて受け渡すと例外処理ロジックのノイズが軽減されます。

```scala
val errorHandler: Try[Try[String]] => Unit = {
    case Success(Failure(_)) => println("Future is Success, but hanage is Failure")
    case Success(_) => println("Success All")
    case Failure(e) => println(s"Future is Failure, because of $e")
}

{
    for {
        result <- Future { throw new Exception; Failure(new Exception) }
    } yield for {
        string <- result
    } yield string
} onComplete errorHandler
```

当然FutureとTryだけでなく、そのほかの全てのモナドで同様のことが可能です。
ただ、モナドの種類だけ結果の値がネストしてしまうので（同一のモナドの結果はflatMapによって潰される）、
なるべくモナドの種類は統一するように心がけよう。