クラウド温泉3.0@小樽のセッション「Monadicプログラミング・マニアックス」で使用するスライドのネタ検討その14です。
Functorよりも強くMonadよりも弱い性質を持つ型クラスにApplicativeがあります。正確にはApplicative Functorという名前がついていますが、型クラス名に合わせてここではApplicativeと呼ぶことにします。
圏論系の技術の中での位置付けは以下のような感じです。
Scalazでの型クラスは定義は以下のような形になります。
Scala Tipsの中では以下の記事が分かりやすいかもしれません。
- Scala Tips / Either (11) - Applicative
- Scala Tips / Either (12) - Applicativeの記述方法
- Scala Tips / Validation (10) - applicative
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の機能の一つと考えておくと分かりやすいでしょう。
Option, Either, Validation
Scala Tipsでは、Option, Eihter, ValidationでのApplicative演算について検討しています。traverseやfoldなどの畳込みとApplicativeも相性がよいので、このあたりも要チェックになります。
- Scala Tips / Option (12) - Monoid
- Scala Tips / Either (10) - 二項演算, AND
- Scala Tips / Either (11) - Applicative
- Scala Tips / Either (12) - Applicativeの記述方法
- Scala Tips / Validation (10) - applicative
- Scala Tips / Validation (12) - parse
- Scala Tips / Validation (14) - オブジェクトの生成
- Scala Tips / Validation (16) - 多重度1の実装
- Scala Tips / Validation (21) - traverse
- Scala Tips / Validation (23) - fold
- Scala Tips / Validation (26) - fold monoid or
- Scala Tips / Validation (30) - foldまとめ
ノート
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 件のコメント:
コメントを投稿