EitherでLeftとRightそれぞれの場合に関数を適用する

基本ぽいけど考え込んでしまった。

stackoverflow.com

Eitherな値でチェーンしているときに、LeftのときにもRightのときにも関数を適用したいという要件があった。 普通に考えれば次のようにすればいい。

scala> val x: Either[Int, Int] = Right(3)
x: Either[Int,Int] = Right(3)

scala> x match {
     |   case Left(e) => e - 1
     |   case Right(x) => x + 1
     | }
res0: Int = 4

パターンマッチで書いてもいいが、Eitherにはfoldがある。

scala> x.fold(_ - 1, _ + 1)
res1: Int = 4

[http://www.scala-lang.org/api/current/scala/util/Either.html#foldC:C:title]

foldというとListのfoldが頭に浮かんでしまい、Eitherでも同じ考え方でfoldが使えるとは思いつきづらい。 Listのfold(実際にはTraversableOnceのメソッド)はfoldLeftと同じためだ(実際の実装も単純なエイリアスになっている)

scala> val y = List(1, 2, 3)
y: List[Int] = List(1, 2, 3)

scala> y.fold(0)((x, y) => x + y + 1)
res5: Int = 9

scala> y.foldLeft(0)((x, y) => x + y + 1)
res6: Int = 9

というようなことがここにまとまっていた。

dev.classmethod.jp