2012年8月6日月曜日

クラウド温泉3.0 (14) / Applicative

クラウド温泉3.0@小樽のセッション「Monadicプログラミング・マニアックス」で使用するスライドのネタ検討その14です。

Functorよりも強くMonadよりも弱い性質を持つ型クラスにApplicativeがあります。正確にはApplicative Functorという名前がついていますが、型クラス名に合わせてここではApplicativeと呼ぶことにします。

圏論系の技術の中での位置付けは以下のような感じです。

Scalazでの型クラスは定義は以下のような形になります。

Scala Tipsの中では以下の記事が分かりやすいかもしれません。

Applicative

ApplicativeはFunctorやMonadと同様にオブジェクトを格納するコンテナかつ計算文脈です。Applicativeの集まりに対して、1つのApplicativeを1つのパラメタとして演算を実行することができます。

演算子|@|がScalazが提供する代表的なApplicative演算子です。

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

ApplicativeのListに対して以下のようにfoldによる畳込みを行うことができます。

scala> List(1.some, 2.some).foldRight(0.some)((x, a) => (x |@| a)(_ + _))
res104: Option[Int] = Some(3)

ApplicativeはTraversableとの組み合わせで畳込み処理を行うこともできます。ApplicativeはTraversableの対象となっているのが重要な性質の一つです。

scala> List(1.some, 2.some).sequence
res92: Option[List[Int]] = Some(List(1, 2))

scala> List(1.some, 2.some).sequence.map(_.foldRight(0)(_ + _))
res111: Option[Int] = Some(3)

ListやOptionあるいはValidationなど、Monad的なオブジェクトはMonadかつApplicativeであることがほとんどなので、プログラミング上はMonadの機能の一つと考えておくと分かりやすいでしょう。

使用例

ApplicativeはValidationと併用するのが典型的な使用例です。

ノート

Applicativeで行う処理の多くは条件が合えばMonoidでも実現することができます。Monoidを使った方が簡潔になるので、可能であればMonoidを使用するのがよいでしょう。

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

scala> List(1.some, 2.some).sequence.map(_.sum)
res96: Option[Int] = Some(3)

scala> List(1.some, 2.some).foldMap(identity)
res100: Option[Int] = Some(3)

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

ApplicativeとMonoidの使い分け、Monoidが使用できる条件判定をプログラミング時に瞬時に判断できるようにしておくのが大事です。

0 件のコメント:

コメントを投稿