REPLでコンパイルエラーと実行時のエラーを勘違いしていた

#### 追記 2

まさに@xuwei_kさんからコメントしていただいた通りで、2点勘違いしていました。

* 型としてmatchする 可能性がある ことと、値が実際にmatchするのを勘違い
* コンパイルエラーと実行時のエラーを勘違い

同じようなコードをREPLじゃなくてファイルで書いたとしても、

```scala
import scala.util.{Failure, Success, Try}

object MatchTest {
  def main(args: Array[String]) {
    val e = Try {
      Option(null)
    } match {
      case Success(Some(n)) => Right(n.toLowerCase)
      case Success(None) => Left("returned None")
      case Failure(e) => Left(e.getMessage)
    }
    println(e)
  }

  /** [値, null, 例外]という3種類の戻りがあるメソッド
    * 実際にはJavaのライブラリの呼び出し */
  def doorSecurity(name: String): String = {
    name match {
      case "Bob" => null
      case "Dave" => throw new RuntimeException("Dave is not allowed")
      case n => n
    }
  }
}
```

コンパイル時にエラーを出してくれます。


    $ scalac MatchTest.scala
    MatchTest.scala:9: error: value toLowerCase is not a member of Null
          case Success(Some(n)) => Right(n.toLowerCase)
                                           ^
    one error found

`Try { Option(null) }`と書いたら戻りの型は`Try[Option[Null]]`になるというのは理解できます。
ただ、以下のように書いたら、`Success(None)`がmatchするのはなぜか？まだ腑に落ちていません。まだ考えが足りない。


```scala
import scala.util.{Try, Success, Failure}


object TryOptionTest {
  def main(args: Array[String]): Unit = {
    val people = List("Alice", "Bob", "Carol", "Dave")
    people map entrance foreach {
      case Right(n) => println(s"Hello $n")
      case Left(m) => println(m)
    }
  }
  
  def entrance(name: String): Either[String, String] = {
    Try {
      Option(doorSecurity(name))
    } match {
      case Success(Some(n)) => Right(n)
      case Success(None) => Left("do not pass null")
      case Failure(e) => Left(e.getMessage)
    }
  }

  /** [値, null, 例外]という3種類の戻りがあるメソッド
    * 実際にはJavaのライブラリの呼び出し */
  def doorSecurity(name: String): String = {
    name match {
      case "Bob" => null
    
  case "Dave" => throw new RuntimeException("Dave is not allowed")
      case n => n
    }
  }
}
```

コンパイル時には、`Try{ Option(doorSecurity(name)) }`の戻り値の型が`Try[Option[String]]`と推論されて、実行時に`doorSecurity`が`null`を返したときには、実際に`Success(None)`になるから、という感じ、でしょうか。

----

旧タイトル: Try(None)からのパターンマッチがSuccess(Some(n))にマッチしてしまう？というのはなかった

#### 追記: 以下の挙動はsbt consoleだけだった。普通にファイル作ってやれば期待通り動いた。

Scala version: 2.10.2

```scala
import scala.util.{Try, Success, Failure}

object TryOptionTest {
  def main(args: Array[String]): Unit = {
    val l1 = List(1, "abc", null)
    l1 foreach f1
  }

  def f1(v: Any): Unit = {
    Try {
      Option(v)
    } match {
      case Success(Some(n)) => println(2)
      case Success(None) => println(1)
      case Failure(e) => println(0)
    }
  }
}
```

    $ scalac TryOptionTest.scala
    $ scala TryOptionTest
    2
    2
    1

よかったです。

----

例えばこんなコードを書いたときに、`Success(None)`にマッチするのを期待してたけど、`Success(Some(n))`にマッチしてしまう。

```
scala> Try {
     | Option(null)  // 本当はなんかOptionに包まれた値が返る処理
     | } match {
     | case Success(Some(n)) => Right(n.doSomething)
     | case Success(None) => Left("returned None")
     | case Failure(e) => Left(e.getMessage)
     | }
<console>:14: error: value getLines is not a member of Null
              case Success(Some(n)) => Right(n.doSomething)
                                               ^
```

入れ子にしてやれば動くかと思ったけど、そういうことでもないようだ。

```
scala> Try {
     | Option(null)
     | } match {
     |   case Success(n) => n match {
     |     case Some(g) => Right(g.doSomething)
     |     case None => Left("returned None")
     |     }
     |   case Failure(e) => Left(e.getMessage)
     | }
<console>:15: error: value doSomething is not a member of Null
                  case Some(g) => Right(g.doSomething)
                                          ^
```

なぜこんな挙動になっているのか、どうやって書くのがよいのか、どなたか教えていただけるととてもうれしいです。

ただの`Success(n)`なら期待した通りに動く。

```
scala> Try {
     | Option(null)
     | } match {
     | case Success(n) => n
     | case Failure(e) => e.getMessage
     | }
res31: java.io.Serializable = None
```
```
scala> Try {
     | Option(123)
     | } match {
     | case Success(n) => n
     | case Failure(e) => e.getMessage
     | }
res32: java.io.Serializable = Some(123)
```