2012年2月20日月曜日

Scala Tips / Either (6) - Left, Right

EitherのサブクラスであるLeftとRightを生成するイディオムです。

Scala

Left[Exception]とRight[Int]は以下のようにして生成します。

val a = Right(10)
val a = Left(new IllegalArgumentException("bad"))

LeftやRightは、Either型のメソッドの返却値として生成することが多く、メソッドのシグニチャで型が記述されている場合には、不足情報を型推論で補ってくれるため通常はこの生成方法でかまいません。

ただし、型推論が効かない局面では困った問題が起きてしまいます。たとえばRight(10)の型はEither[Exception, Int]ではなくRight[Nothing, Int]にLeft(new IllegalArgumentException("bad"))の型もEither[Exception, Int]ではなくLeft[java.lang.IllegalArgumentException,Nothing]になってしまいます。

scala> val a = Right(10)
a: Right[Nothing,Int] = Right(10)

scala> val a = Left(new IllegalArgumentException("bad"))
a: Left[java.lang.IllegalArgumentException,Nothing] = Left(java.lang.IllegalArgumentException: bad)

このため、型をEither[Exception, Int]にするためには以下のように変数定義に記述するか:

val a: Either[Exception, Int] = Right(10)
val a: Either[Exception, Int] = Left(new IllegalArgumentException("bad"))

オブジェクト側に型注釈を付ける必要があります。

val a = Right(10): Either[Exception, Int]
val a = Left(new IllegalArgumentException("bad")): Either[Exception, Int]

いずれもかなり冗長ですね。

Scalaz

Scalazでは、以下の記述方法でEither型のインスタンスとしてLeftとRightを生成することが可能です。

val a = 10.right[Exception]
val a = new IllegalArgumentException("bad").left[Int]

「10.right[Exception]」のように任意のオブジェクトのrightメソッド(Scalazが追加)によってEither[Exception, Int]型のインスタンスとしてRight[Exception, Int]を生成することができます。

leftの場合も基本的には同様ですが、上の例ではEither[Exception, Int]ではなくてEither[IllegalArgumentException, Int]になってしまいます。

scalazの場合も、このように指定する具象オブジェクトが、目的とする型のサブクラスの場合には、型注釈などを用いて陽に指定する必要があります。

scala> 10.right[Exception]
res1: Either[Exception,Int] = Right(10)

scala> new IllegalArgumentException("bad").left[Int]
res9: Either[java.lang.IllegalArgumentException,Int] = Left(java.lang.IllegalArgumentException: bad)

scala> new IllegalArgumentException("bad").left: Either[Exception, Int]
res10: Either[Exception,Int] = Left(java.lang.IllegalArgumentException: bad)

ノート

Right/Leftの生成方法については、Option(11) - Some/Noneも参考になると思います。

諸元

  • Scala 2.9.1
  • Scalaz 6.0.3

0 件のコメント:

コメントを投稿