scalaz.Bifunctor と Either

前回メモし忘れていた Either の小ネタを紹介。
例の如く scalaz の import は必須。

import scalaz._
import Scalaz._

Either を取得した後、普通は、処理の分岐を下記のように記述する。

1.right[String] match {
  case Right(n :Int) => n + 1
  case Left(s: String) => "[" + s + "]"
}

scalaz には Bifunctor があるので、下記のようにも書ける。

val fr: PartialFunction[Int, Int] = {case n => n + 1}
val fl: PartialFunction[String, String] = {case s => "[" + s + "]"}
fl <-: 1.right[String] :-> fr

別に PartialFunction である必要はなく Function でも良い。
下記に、幾つか例を示す。

(fl <-: 1.right[String] :-> fr) assert_=== 2.right[String]
(fl <-: 1.right[String] :-> fr :-> fr) assert_=== 3.right[String]
(fl <-: "foo".left[Int] :-> fr) assert_=== "[foo]".left[Int]
(fl <-: fl <-: "foo".left[Int] :-> fr) assert_=== "[[foo]]".left[Int]

scalaz.Bifunctor は、Either だけではなく Tuple2 や Validation でも使える。

(fl <-: 1.success[String] :-> fr) assert_=== 2.success[String]
(fl <-: ("foo", 1) :-> fr) assert_=== ("[foo]", 2)

Tuple2 の時は両方評価される。ちょっと Allow の *** に似てるかも。