2012年4月10日火曜日

Scala Tips / Either (19) - Optionと相互変換

EitherとOptionの相互変換のイディオムです。

EitherのRightを成功、Leftを失敗として扱うことを想定しています。逆の場合は、成否の判定を反転させてください。

(分類の基準)

Java風

Option→Either

OptionをEitherに変換する場合は、OptionのifDefinedメソッドでSome(成功の文脈)の判定を行い、Someの場合はその値をRightに、そうでない場合は失敗の内容を示す値(この場合はThrowable)をLeftに詰めます。

  1. def f[T](o: Option[T], e: Throwable): Either[Throwable, T] = {  
  2.   if (o.isDefined) Right(o.get) else Left(e)  
  3. }  

Optionでは、成功と失敗の切り分けはできますが、失敗の内容を示す値は保持していないので、外側から指定する必要があります。

Either→Option

EitherをOptionに変換する場合は、EitherのisRihtメソッドで成功(Right)であることを確認した後、rightメソッドで取得したRightProjectionのrightメソッドを用いて値を取り出し、Someに詰めます。EitherがLeftの場合は、Left側の値は捨ててNoneを返します。

  1. def f[T](e: Either[Throwable, T]): Option[T] = {  
  2.   if (e.isRight) Some(e.right.get)  
  3.   else None  
  4. }  

Scala風

Option→Either

OptionをEitherに変換する場合は、match式を用いて、SomeとNoneの判定を行い、Someの場合は格納されている値をRightに詰めます。Noneの場合は、失敗を示す値をLeftに詰めます。

  1. def f[T](o: Option[T], e: Throwable): Either[Throwable, T] = {  
  2.   o match {  
  3.     case Some(s) => Right(s)  
  4.     case None => Left(e)  
  5.   }  
  6. }  
Either→Option

EitherをOptionに変換する場合は、match式でLeftまたはRightを判定し、Rightの場合は取得した値をSomeに詰めます。Leftの場合は、Left側の値は捨ててNoneを返します。

  1. def f[T](e: Either[Throwable, T]): Option[T] = {  
  2.   e match {  
  3.     case Right(s) => Some(s)  
  4.     case Left(_) => None  
  5.   }  
  6. }  

Scala

Option→Either

OptionをEitherに変換するMonadicな演算はないと思います。Scala風で説明したmatch式方式を用いるとよいでしょう。

Either→Option

EitherをOptionに変換する場合、Eitherのfoldメソッドを使うことができます。

  1. def f[T](e: Either[Throwable, T]): Option[T] = {  
  2.   e.fold(_ => None, Some(_))  
  3. }  

Scalaz

Option→Either

Scalazでは、OptionをValidationに変換するtoSuccessメソッドが追加されています。ValidationはさらにEitherに変換するeitherメソッドを持っているので、これを連結して使用します。

  1. def f[T](o: Option[T], e: Throwable): Either[Throwable, T] = {  
  2.   o.toSuccess(e).either  
  3. }  
Either→Option

ScalazではEitherをOptionに変換する便利なメソッドは用意していません。Javaで説明したfoldメソッドを用いるとよいでしょう。

ノート

EitherとOptionの相互変換は以下の手法がよいでしょう。

Either→Option
Eitherのfoldメソッド (Scala)
Option→Either
Validation経由 (Scalaz)

性能を重視する場合はJava風、ScalaやScalazの技が思い浮かばなかった場合はScala風のmatch式が安全策です。

諸元

  • Scala 2.9.1
  • Scalaz 6.0.3

0 件のコメント:

コメントを投稿