2012年7月6日金曜日

Scala Tips / Option (13) - Monoid 短絡OR

前回はScalazのOptionはMonoidとしても使用できる事を説明しました。

scala> 1.some |+| 2.some
res10: Option[Int] = Some(3)

scala> 1.some |+| none
res11: Option[Int] = Some(1)

scala> none |+| 2.some
res12: Option[Int] = Some(2)

scala> none[Int] |+| none[Int]
res14: Option[Int] = None

scala> List(1.some, 2.some, 3.some, 4.some).sumr
res32: Option[Int] = Some(10)

scala> List(1.some, 2.some, none, 4.some).sumr
res20: Option[Int] = Some(7)

Optionのコンテナ側の畳込み戦略はOR演算でした。この場合は、Noneでないものをすべて足し込むという振舞いになります。

短絡OR

コンテナ側の畳込み戦略として短絡評価も考えられます。

短絡評価では、最初に有効となった値が使用されます。

Scalazでは短絡評価のモノイド演算を行うOptionとしてFirstOptionを提供しています。OptionのfstメソッドでFirstOptionを取得できます。

scala> 1.some.fst
res42: scalaz.FirstOption[Int] = Some(1)

FirstOption同士を演算子|+|でモノイド演算すると以下のように最初に登場したSomeが使用されます。

scala> 1.some.fst |+| 2.some.fst
res15: scalaz.FirstOption[Int] = Some(1)

scala> 1.some.fst |+| none.fst
res44: scalaz.FirstOption[Int] = Some(1)

scala> none.fst |+| 2.some.fst
res45: scalaz.FirstOption[Int] = Some(2)

scala> none[Int].fst |+| none[Int].fst
res48: scalaz.FirstOption[Int] = None

短絡ORは畳込みで使用すると効果がみえてきます。いずれの場合も最初に登場した(先頭に近い)Someが使用されます。

scala> List(1.some, 2.some, 3.some, 4.some).map(_.fst).sumr
res35: scalaz.FirstOption[Int] = Some(1)

scala> List(1.some, 2.some, none, 4.some).map(_.fst).sumr
res37: scalaz.FirstOption[Int] = Some(1)

scala> List(none, 2.some, 3.some, 4.some).map(_.fst).sumr
res36: scalaz.FirstOption[Int] = Some(2)

LastOption

短絡ORとは反対に、最後に登場したSomeを使いたいケースもあるかもしれません。Scalazはその用途に使用できるLastOptionを提供しています。

OptionのlstメソッドでLastOptionを取得できます。

scala> 1.some.lst
res49: scalaz.LastOption[Int] = Some(1)

LastOption同士を演算子|+|でモノイド演算すると以下のように最後に登場したSomeが使用されます。

scala> 1.some.lst |+| 2.some.lst
res18: scalaz.LastOption[Int] = Some(2)

scala> 1.some.lst |+| none.lst
res51: scalaz.LastOption[Int] = Some(1)

scala> none.lst |+| 2.some.lst
res52: scalaz.LastOption[Int] = Some(2)

scala> none[Int].lst |+| none[Int].lst
res53: scalaz.LastOption[Int] = None

LastOptionをsumrメソッドで使用すると以下の振舞いになります。いずれも最後のSomeが畳込み結果となります。

scala> List(1.some, 2.some, 3.some, 4.some).map(_.lst).sumr
res38: scalaz.LastOption[Int] = Some(4)

scala> List(1.some, 2.some, none, 4.some).map(_.lst).sumr
res39: scalaz.LastOption[Int] = Some(4)

scala> List(none, 2.some, 3.some, 4.some).map(_.lst).sumr
res40: scalaz.LastOption[Int] = Some(4)

scala> List(1.some, 2.some, 3.some, none).map(_.lst).sumr
res41: scalaz.LastOption[Int] = Some(3)

諸元

  • Scala 2.9.2
  • Scalaz 6.0.4

0 件のコメント:

コメントを投稿