Either

Either エフェクトは Option エフェクトに似ているが、計算が止まった理由を含める能力を追加している。

import org.atnos.eff._, all._, syntax.all._

  /**
   * スタックの宣言
   */
  type S = Fx.fx1[Either[String, *]]

  // このスタックを計算
  val map: Map[String, Int] =
    Map("key1" -> 10, "key2" -> 20)

  // マップから2つのキーを取りだし、それらに対応する値を結合する
  def addKeys(key1: String, key2: String): Eff[S, Int] = for {
    a <- optionEither(map.get(key1), s"'$key1' not found")
    b <- optionEither(map.get(key2), s"'$key2' not found")
  } yield a + b

  (addKeys("key1", "key2").runEither.run, addKeys("key1", "missing").runEither.run)

> (Right(30),Left('missing' not found))

catchLeft メソッドは、エラーを傍受して場合により復旧させるために使うことができる。

  case class TooBig(value: Int)
  type E = Fx.fx1[Either[TooBig, *]]

  val i = 7

  val value: Eff[E, Int] =
    if (i > 5) left[E, TooBig, Int](TooBig(i))
    else       right[E, TooBig, Int](i)

  val action: Eff[E, Int] = catchLeft[E, TooBig, Int](value) { case TooBig(k) =>
    if (k < 10) right[E, TooBig, Int](k)
    else        left[E, TooBig, Int](TooBig(k))
  }

  action.runEither.run ==== Right(7)

備考: leftright の型注釈は、スコープ内宣言を追加することで避けられる。詳しくは Implicits セクションで学べる。