ScalaでOption[Int]
をEither[String, Int]
に変換する必要があるとします。私はこのようにしたい:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number")) {x => Right(x)}
残念ながら、上記のコードはコンパイルされず、タイプEither[String, Int]
を明示的に追加する必要があります。
ox.fold(Left("No number"): Either[String, Int]) { x => Right(x) }
タイプを追加せずにこの方法でOption
をEither
に変換することは可能ですか?Option
をEither
に変換することをどのように提案しますか?
いいえ、この方法で行う場合、タイプを除外することはできません。
Left("No number")
の型は_Either[String, Nothing]
_であると推測されます。ちょうどLeft("No number")
から、コンパイラはEither
の2番目の型をInt
にしたいことを知ることができず、型推論はコンパイラがそれ程遠くまで行かないメソッド全体を見て、_Either[String, Int]
_であると決定します。
これはさまざまな方法で行うことができます。パターンマッチングの例:
_def foo(ox: Option[Int]): Either[String, Int] = ox match {
case Some(x) => Right(x)
case None => Left("No number")
}
_
または、if
式を使用:
_def foo(ox: Option[Int]): Either[String, Int] =
if (ox.isDefined) Right(ox.get) else Left("No number")
_
または_Either.cond
_を使用:
_def foo(ox: Option[Int]): Either[String, Int] =
Either.cond(ox.isDefined, ox.get, "No number")
_
どのバージョンのScala=を使用していたのかわかりません。現在、Scala 2.12.6では、このようなコードでコンパイルの問題はありません。
_def foo(ox: Option[Int]): Either[String, Int] =
ox.toRight("No number")
_
私がもう1つ言いたいのは、折り畳み(折り畳みメソッドを持っているものはほとんど折りたたむのが私の好みの方法ですが)はかなり頻繁に型パラメータの助けを必要とすることです。コンパイラーが式を型チェックできる方法は2つあります。型パラメーターを推測する方法と、明示的に定義されたパラメーターを見つける方法です。
あなたの例では、次のようにオプションを折りたたむ場合:
_def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number") : Either[String, Int])(x => Right(x))
_
最初の引数に関する型情報を明示的に提供し、それを使用してfold
の型パラメーターを推測できます。型推論メカニズムを支援しています。
一方、次のようにfold
の型パラメーターを単に明示的に指定することもできます。
_def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(x => Right(x))
_
これで、実際の(値レベルの)引数には余分な型情報が散らばらず、コンパイラーがそれを調べたときに型推論が行われなくなり、明示的に提供されているfold
の型パラメーターがすぐにわかります。角括弧を使用して、typeパラメーターを明示的に指定します。
x => Right(x)
に関するもう1つのポイントは、Right caseクラスのコンパニオンオブジェクトのapply
メソッドにxを渡す以外は何もしない新しい関数リテラルを実際に作成していることです。適切な形状の機能がすでに利用可能です。 x
を取り、Right(x)
を返します。 apply
メソッドです。直接参照する(渡す)ことができます。
_def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(Right.apply)
_